Read mapping
Map reads
Any renaming of files needs to happen before fastq-files are mapped. The population designation (before underscore) is used by FreeBayes to call SNPs so it is important that population designation make biological sense.
Values chosen for reduced representation reference:
Transfer copy of reference.fasta and associated files Reference constructed using c = 0.8, K1 = 5, and K2 = 2. into each directory containing demultiplexed and quality trimmed data/SEQ
Run dDocent from within each Library directory to map reads to reference.fasta.
Write configuration file to run dDocent in each reference directory.
Execute dDocent from within each reference folder to initiate a run to map individuals to reduced representation reference and call SNPs.
QA/QC read mapping
Query mapping statistics
During the mapping stage, dDocent calls BWA to map reads from the individuals in the folder to the generated reduced representation reference and create a -RG.bam-file for each individual. The second column of a BAM (or SAM) file contains FLAGs with binary encoded information on mapping quality, pairedness etc. that can be used to compare the mapping efficiency to the reduced representation reference.
The number of reads mapped can be counted using samtools idxstats <aln-RG.bam> which retrieves stats from the bam-file. The output is TAB-delimited file with each line consisting of the reference sequence name, sequence length, # mapped reads and # unmapped (empty) reads. In addition, samtools can also be be used to query samtools flagstat file.bam which returns an output containing the number of reads for which each flag is true.
dDocent creates a file called bamlist.list containing all the bam files that were generated during read mapping in dDocent using BWA. Write script to gather flagstats from all bam-files.
# Sequence folders
SEQ <- c("BMA-1", "BMA-2", "BMA-3")
# write script to gather flagstats
l <- list()
for (s in SEQ){
l[[s]] <- read_table2(paste("data/SEQ/", s, "/bamlist.list", sep =""), col_names = "BAM") %>%
mutate(PATH = paste("data/SEQ/", s, "/", sep = ""),
COMMAND = "samtools flagstat",
OUT = paste(">> data/SEQ/", s, ".flagstats", sep = "")) %>%
select( COMMAND, PATH, BAM, OUT) %>%
unite(FILE, 2:3, sep = "")
}
bam <- ldply(l, data.frame) %>%
select(-`.id`)
write_delim(bam, "scr/flagstats.sh", delim = "\t", col_names = FALSE)
Run flagstats.
Write script to gather idxstats from all bam-files.
# write script to gather idxstats
l <- list()
l[["BMA1"]] <- read_table2("data/SEQ/BMA-1/bamlist.list", col_names = "BAM") %>%
mutate(PATH = "data/SEQ/BMA-1/",
COMMAND = "samtools idxstats",
OUT = ">> data/SEQ/BMA1.idxstats") %>%
select( COMMAND, PATH, BAM, OUT) %>%
unite(FILE, 2:3, sep = "")
l[["BMA2"]] <- read_table2("data/SEQ/BMA-2/bamlist.list", col_names = "BAM") %>%
mutate(PATH = "data/SEQ/BMA-2/",
COMMAND = "samtools idxstats",
OUT = ">> data/SEQ/BMA2.idxstats") %>%
select( COMMAND, PATH, BAM, OUT) %>%
unite(FILE, 2:3, sep = "")
l[["BMA3"]] <- read_table2("data/SEQ/BMA-3/bamlist.list", col_names = "BAM") %>%
mutate(PATH = "data/SEQ/BMA-3/",
COMMAND = "samtools idxstats",
OUT = ">> data/SEQ/BMA3.idxstats") %>%
select( COMMAND, PATH, BAM, OUT) %>%
unite(FILE, 2:3, sep = "")
bam <- ldply(l, data.frame) %>%
select(-`.id`)
write_delim(bam, "scr/idxstats.sh", delim = "\t", col_names = FALSE)
Run indxstats.
Evaluate & compare mapping results
Compare number of reference contigs for which no reads mapped to per library.
mapstats <- read_delim("results/BWA_mapping.stats", delim = " ")
# plot no of loci vs "empty" loci
p1 <- ggplot(mapstats, aes(x = Lib, y = CONTIGS_MAPPED)) +
geom_bar(stat = "identity", color = "black", fill = "darkorange") +
scale_y_continuous(limits = c(0, 0.05)) +
labs(x = "library", y = "% contigs w/no reads mapped") +
theme_standard
p2 <- ggplot(mapstats, aes(x = Lib, y = Reads_Mapped)) +
geom_bar(stat = "identity", color = "black", fill = "darkorange") +
labs(x = "library", y = "mean reads mapped per indv") +
theme_standard
p3 <- ggplot(mapstats, aes(x = Lib, y = PROP_MISMATCH)) +
geom_bar(stat = "identity", color = "black", fill = "darkorange") +
labs(x = "",y = "% reads not mapped as pair") +
theme_standard
multiplot(p1, p2, p3, cols = 3)

SNP calling
Transfer copy of reference.fasta and associated files into SNP calling directory.
Create symlinks from all fq, bam and bam.bai-files for each separately mapped library in SNP_Calling folder.
Execute dDocent from within SNP_Calling-folder to call variants across all individuals (all libraries).
File TotalrawSNPs.vcf contains all raw SNP/INDEL calls. Do not need to keep links of fq.gz-, bam-, .bam.bai-files after SNPs have been called. Copy TotalRaSNPs.vcf to VCF for SNP filtering.
SNP filtering
dDocent uses FreeBayes to call SNPs and write a VCF-file TotalrawSNPs.vcf. This data set was filtered to remove low quality and artefactual SNP sites, paralogs and low quality individuals based on levels of missing data, minimum/maximum read depth, genotype call rate, and minor allele frequencies. Contigs may contain more than one SNP; the script rad_haplotyper.pl was used to create haplotypes for each locus.
Raw data
Individuals/Populations sampled
Generate a list of all individuals included in the SNP data set called by FreeBayes in the dDocent pipeline.
Use Ind_raw file to write text files of individuals in each library and in regional groupings.
# import individuals in raw data set ----
Ind_RAW <- read_delim("data/VCF/raw.ind", delim = "\t", col_names = "LIB_ID") %>%
separate(LIB_ID, into = c("SP", "WELL", "SAMPLE_ID"), sep = "_", remove = FALSE, extra = "merge")
# create files with individuals by population ----
SampleInfo <- read_delim("data/POPGEN/SampleInfo.txt", delim = "\t")
Ind_RAW <- left_join(Ind_RAW, SampleInfo)
pops <- unique(Ind_RAW$POP)
for (p in pops){
df <- Ind_RAW %>%
filter(POP == p) %>%
select(LIB_ID)
write_delim(df, paste("data/VCF/", p, ".ind", sep = ""),
delim = "", col_names = FALSE)
}
# create files with individuals per library ----
temp <- Ind_RAW %>%
filter(grepl("1A", WELL) |
grepl("1B", WELL)) %>%
select(LIB_ID)
write.table(temp, "data/VCF/BMA1.ind",
col.names = FALSE, row.names = FALSE, quote = FALSE)
temp <- Ind_RAW %>%
filter(grepl("2A", WELL) |
grepl("2B", WELL)) %>%
select(LIB_ID)
write.table(temp, "data/VCF/BMA2.ind",
col.names = FALSE, row.names = FALSE, quote = FALSE)
temp <- Ind_RAW %>%
filter(grepl("3A", WELL) |
grepl("3B", WELL)) %>%
select(LIB_ID)
write.table(temp, "data/VCF/BMA3.ind",
col.names = FALSE, row.names = FALSE, quote = FALSE)
Compare Individual & SNP stats
Use VCFtools to create stats files for depth, missing data, heterozygosity and site quality for the raw data.
Compare raw stats.
# load stats files ----
ind_stats_raw <- read.ind.stats(dir = "data/VCF", vcf = "BMA_raw") %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)
loc_stats_raw <- read.loc.stats(dir = "data/VCF/", vcf = "BMA_raw")
# plot missing data per indv ----
p1 <- ggplot(ind_stats_raw, aes(x = MISS_BMA_raw)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.5),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "missing data per indv") +
theme_standard
# plot read depth per indv ----
p2 <- ggplot(ind_stats_raw, aes(x = MEAN_DEPTH_BMA_raw)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per indv") +
theme_standard
# plot depth vs missing ----
p3 <- ggplot(ind_stats_raw, aes(x = MEAN_DEPTH_BMA_raw, y = MISS_BMA_raw)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.5),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per indv", y = "% missing data") +
theme_standard
# plot Fis per indv ----
p4 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv") +
theme_standard
# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw, y = MISS_BMA_raw)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.5),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "% missing data") +
theme_standard
# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw, y = MEAN_DEPTH_BMA_raw)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "mean depth per indv") +
theme_standard
# plot distribution missing data per locus ----
p7 <- ggplot(loc_stats_raw, aes(x = MISS_BMA_raw)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "% missing data per locus") +
theme_standard
# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_raw, aes(x = MEAN_DEPTH_BMA_raw)) +
geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per locus") +
theme_standard
# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_raw, aes(x = MEAN_DEPTH_BMA_raw, y = MISS_BMA_raw)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "% missing data") +
theme_standard
# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA_raw.lqual",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(PROB = 10^(-QUAL/10))
temp <- data.frame(loc_stats_raw$MEAN_DEPTH_BMA_raw, site_qual$QUAL) %>%
rename(depth = loc_stats_raw.MEAN_DEPTH_BMA_raw, qual = site_qual.QUAL)
p10 <- ggplot(temp, aes(x = depth, y = qual)) +
geom_point(size = 1) +
geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "SNP quality") +
theme_standard
# plot number of SNPs per contig vs. mean depth ----
temp <- loc_stats_raw %>%
count(CHR)
p11 <- left_join(temp, loc_stats_raw) %>%
ggplot() +
geom_point(aes(x = n, y = MEAN_DEPTH_BMA_raw)) +
labs(x = "number of SNPs per contig", y = "mean depth") +
theme_standard
# plot no of SNPs per locus ----
p12 <- loc_stats_raw %>%
count(CHR) %>%
ggplot(aes(x = n)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
labs(x = "number of SNPs per locus") +
theme_standard
mraw <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

Choose threshold values for quality score, coverage, missing data, minor alleles and mapping/variant calling artifacts
Filter 0: Remove LQ individuals
Remove (known) low quality individuals from data set:
Identify low quality individuals to remove from the data set; defined as individuals with a mean coverage of five or less reads across all loci, with more than 31% missing data, or Fis > (thresholds based on exploratory filtering).
[1] 18
Remove low quality individuals and decompose indels.
Compare stats:
Data set contains 406 individuals and 1311068 loci after removing low quality individuals and decomposing indels set into SNPs.
Import singletons and genotype depth file to create list of loci to exclude based on depth.
Data set contains nrow(singletons) singletons.
Of those nrow(doubletons) are called as a homozygote in one individual.

The data set contains nrow(contigs_total) contigs, nrow(contigs_singletons) (2round( (nrow(contigs_singletons)/nrow(contigs_total)*100), digits = 2)%) contain singletons.

Target coverage is 20 reads per locus; flag singletons with depth < 10 reads and doubletons with depth < 20 reads.
Distriubtion of genotype depth per singleton/doubleton.

Quantiles distribution of read depth for SNP loci called in only one individual.
5% 25% 50% 75% 95% 99%
1 3 5 10 32 139
Distribution of doubletons (homzygous genotype for that individual) and singletons (heterozygote genotype).

Quantiles distribution number of singletons called in one individual.
1% 5% 25% 50% 75% 99%
46.00 56.00 88.75 327.50 534.25 1815.90
Compare the number of SNPs vs complex variants (INDELs).
Filter 1: Confidence in SNP call
The QUAL column of a VCF file is a phred based score indicating the probability that the variant shown in the ALT column is wrong. Given the Phred quality score (Q), and the probability that a base is incorrectly called (P), Q = -10(Log10P). A quality score of 20 indicates, a 1 in 100 chance that the SNP site has been called incorrectly (i.e. 99% probability that correct call).
Filter loci with quality score < 20 and singletons/doubletons with low read depth (<10/20 reads). Code genotypes with genotype call quality < 20 or genotype depth < 5 as missing.
Compare stats post-filtering.
Data set contains 406 individuals and 307278 SNP sites.
Removing low confidence SNP loci and genotype calls results in a reduction in the number of the (maximum) SNPs per locus.
p1 <- loc_stats_raw %>%
count(CHR) %>%
ggplot(aes(x = n)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(n, na.rm = TRUE)),
color = "darkblue", linetype = "dashed", size = 1) +
scale_x_continuous(limits = c(0, 100)) +
labs(x = "number of SNPs per locus") +
theme_standard
p2 <- loc_stats_F1 %>%
count(CHR) %>%
ggplot(aes(x = n)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(n, na.rm = TRUE)),
color = "darkblue", linetype = "dashed", size = 1) +
scale_x_continuous(limits = c(0, 100)) +
labs(x = "number of SNPs per locus") +
theme_standard
m1a <- multiplot(p1, p2, cols=1)

Coding genotypes with low read depth (< 5) as missing, results in an overall increase in missing data per locus and a shift in more individuals with more missing data - this is because individuals (and loci) with coverage issues are now characterized by higher missing data.
iraw <- read.table("data/VCF/BMA_raw.imiss",
header = TRUE, stringsAsFactors = FALSE) %>%
select(INDV, F_MISS) %>%
rename(raw = F_MISS)
imiss <- read.table("data/VCF/BMA.F1.imiss",
header = TRUE, stringsAsFactors = FALSE) %>%
select(INDV, F_MISS) %>%
rename(F1 = F_MISS)
imiss <- left_join(imiss, iraw)
p1 <- ggplot(imiss, aes(x = raw, y = F1)) +
geom_point(shape = 1) +
geom_abline(slope = 1, color = "darkblue", linetype = "dashed", size = 1) +
scale_x_continuous(limits = c(0, 1)) +
scale_y_continuous(limits = c(0, 1)) +
labs(x = "indv missing data raw", y = "indv missing data F1") +
theme_standard
lraw <- read.table("data/VCF/BMA_raw.lmiss",
header = TRUE, stringsAsFactors = FALSE) %>%
select(CHR, POS, F_MISS) %>%
rename(raw = F_MISS)
lmiss <- read.table("data/VCF/BMA.F1.lmiss",
header = TRUE, stringsAsFactors = FALSE) %>%
select(CHR, POS, F_MISS) %>%
rename(F1 = F_MISS)
lmiss <- left_join(lmiss, lraw)
p2 <- ggplot(lmiss, aes(x = raw, y = F1)) +
geom_point(shape = 1) +
geom_abline(slope = 1, color = "darkblue", linetype = "dashed", size = 1) +
scale_x_continuous(limits = c(0, 1)) +
scale_y_continuous(limits = c(0, 1)) +
labs(x = "loci missing data raw", y = "loci missing data F1") +
theme_standard
m1b <- multiplot(p1, p2, cols=2)

Compare depth individuals after removing LQ SNP loci and genotypes.
iraw <- read.table("data/VCF/BMA_raw.idepth",
header = TRUE, stringsAsFactors = FALSE) %>%
select(INDV, MEAN_DEPTH) %>%
rename(raw = MEAN_DEPTH)
idepth <- read.table("data/VCF/BMA.F1.idepth",
header = TRUE, stringsAsFactors = FALSE) %>%
select(INDV, MEAN_DEPTH) %>%
rename(F1 = MEAN_DEPTH)
idepth <- left_join(iraw, idepth)
ggplot(idepth, aes(x = raw, y = F1)) +
geom_point(shape = 1) +
geom_abline(slope = 1, color = "darkblue", linetype = "dashed", size = 1) +
scale_x_continuous(limits = c(0, 150)) +
scale_y_continuous(limits = c(0, 150)) +
labs(x = "mean depth ind raw", y = "mean depth ind F1") +
theme_standard

Filter 2: Genotype call rate and allowed missing data per indv
Remove loci with genotype call rate < 50% and minimum mean depth < 15 reads across all individuals.
Compare distribution of missing data per locus per library.
# create empty list
loc_missing <- list()
for (i in 1:3) {
lib <- paste("BMA", i, sep = "")
loc_missing[[i]] <- read_delim(paste("data/VCF/", lib, ".lmiss", sep = ""), delim = "\t") %>%
select(CHR, POS, F_MISS) %>%
mutate(LIB = lib)
}
# create data frame with all information
loc_missing <- ldply(loc_missing, data.frame)
ggplot(loc_missing, aes(x = F_MISS)) +
geom_histogram(binwidth = .1, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = 0.5),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "missing data per locus") +
facet_grid(LIB ~ .) +
theme_standard

Flag loci that were not called in > 50% of individuals in a given library.
A total of
loci were called in less than 50% of individuals in one or more libraries. Loci being inconsistently called between libraries can result in library effects.
Compare distribution of missing data per locus per sample location.
# create empty list
loc_missing <- list()
# pops to loop over
pop <- unique(Ind_RAW$POP)
# import missing data per locus
for (p in pop) {
loc_missing[[p]] <- read_delim(paste("data/VCF/", p, ".lmiss", sep = ""), delim = "\t") %>%
select(CHR, POS, F_MISS) %>%
mutate(POP = p)
}
# create data frame with all information
loc_missing <- ldply(loc_missing, data.frame) %>%
select(-`.id`)
ggplot(loc_missing, aes(x = F_MISS)) +
geom_histogram(binwidth = .05, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = 0.25),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "missing data per locus") +
facet_grid(POP ~ .) +
scale_y_sqrt() +
theme_standard

Flag loci that were not called in > 75% of individuals at a given sample location.
Remove loci that were not consistently called across all libraries and sample locations.
Identify individuals with > 25% missing data

Remove flagged individuals.
Analyze stats post-filtering:
Filter 3: Filter loci and individuals based on depth, variance in depth and genotype call rate
Determine mean depth and variance per locus per library.
Compare distribution of depth coverage per locus per library. Identify loci that do not have consistent coverage between libraries (can lead to library effects), and/or across individuals.
# create empty list
loc_depth <- list()
# import depth data per locus
loc_depth[[1]] <- read.table("data/VCF/BMA1.ldepth.mean",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(LIB = "BMA1")
loc_depth[[2]] <- read.table("data/VCF/BMA2.ldepth.mean",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(LIB = "BMA2")
loc_depth[[3]] <- read.table("data/VCF/BMA3.ldepth.mean",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(LIB = "BMA3")
# create data frame with all information
loc_depth <- ldply(loc_depth, data.frame)
ggplot(loc_depth, aes(x = MEAN_DEPTH)) +
geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(xintercept = 20,
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus") +
facet_grid(LIB ~ .) +
theme_standard

Identify loci with large variance in mean depth across libraries and/or individuals by calculating the coefficient of variance (STD/MEAN).
Compare mean across all individual to mean weighted by library and coefficient of variance of read depth across individuals and between libraries:
p1 <- ggplot(depth_comp, aes(x = MEAN_DEPTH, y = MEAN)) +
geom_point(shape = 1) +
labs(x = "mean depth per locus", y = "mean weighted by lib") +
geom_abline(slope = 1, linetype = "dashed", color = "darkred", size = 1) +
theme_standard
p2 <- ggplot(depth_comp, aes(x = COEFF_VAR_IND)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = quantile(COEFF_VAR_IND, .99)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "coeff var depth across all indv") +
theme_standard
p3 <- ggplot(depth_comp, aes(x = COEFF_VAR_IND, y = COEFF_VAR_LIB)) +
geom_point(shape = 1) +
scale_x_continuous(limits = c(0, 200)) +
scale_y_continuous(limits = c(0, 100)) +
labs(x = "coeff var depth across all indv", y = "coeff var mean depth betw lib") +
theme_standard
p4 <- ggplot(depth_comp, aes(x = COEFF_VAR_LIB)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = quantile(COEFF_VAR_LIB, .99)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "coeff var depth between lib") +
theme_standard
m3a <- multiplot(p1, p2, p3, p4, cols=2)

If loci have consistent coverage across loci the mean read depth per locus across all individuals and weighted by library should fall on the red diagonal.
Flag loci that have high variation in mean coverage between individuals and between libraries.
Remove loci flagged for high variance in depth across all individuals and between libraries (removes library effects), filter loci with mean depth < 20 and genotype call rate < 75%
Compare mean depth and number of sites called per individual.

Use genotype depth file to identify individuals with high variance in read depth across loci.
# number of individuals
n <- nrow(ind_stats_F2)+1
# read genotype depth & code values < 5 as missing
gdepth <- read_table2("data/VCF/BMA.F3a.gdepth") %>%
select(-POS) %>%
distinct(CHROM, .keep_all = TRUE) %>%
gather(key = INDV, value = DEPTH, 3:n) %>%
mutate(DEPTH = as.numeric(gsub(-1, 0, DEPTH)),
DEPTH = as.numeric(gsub("\\<1\\>", 0, DEPTH)),
DEPTH = as.numeric(gsub("\\<2\\>", 0, DEPTH)),
DEPTH = as.numeric(gsub("\\<3\\>", 0, DEPTH)),
DEPTH = as.numeric(gsub("\\<4\\>", 0, DEPTH)))
# calculate summary statistics
idepth <- gdepth %>%
group_by(INDV) %>%
summarize(TOTAL = sum(DEPTH),
MAX = max(DEPTH),
MEAN_NON0 = mean(DEPTH[DEPTH > 0]),
MEAN = mean(DEPTH),
MEDIAN = median(DEPTH),
VAR = var(DEPTH),
STD = sd(DEPTH)) %>%
mutate(COEFF_VAR = STD/MEAN,
RATIO_MEAN_MEDIAN = MEAN/MEDIAN)
idepth <- left_join(idepth, ind_stats_F2)
Compare variability of depth within individuals.
p1 <- ggplot(idepth, aes(x = MAX, y = TOTAL)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p2 <- ggplot(idepth, aes(x = TOTAL, y = VAR)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p3 <- ggplot(idepth, aes(MAX, MEDIAN)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p4 <- ggplot(idepth, aes(x = MEAN, y = MEDIAN)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p5 <- ggplot(idepth, aes(x = COEFF_VAR, y = RATIO_MEAN_MEDIAN)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p6 <- ggplot(idepth, aes(MEAN)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(xintercept = 15, color = "darkred", linetype = "dashed") +
theme_standard
p7 <- ggplot(idepth, aes(MEDIAN)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(xintercept = 10, color = "darkred", linetype = "dashed") +
theme_standard
p8 <- ggplot(idepth, aes(RATIO_MEAN_MEDIAN)) +
geom_histogram(binwidth = 0.1, color = "black", fill = "darkorange") +
theme_standard
p9 <- ggplot(idepth, aes(COEFF_VAR)) +
geom_histogram(binwidth = 0.025, color = "black", fill = "darkorange") +
theme_standard
p10 <- ggplot(idepth, aes(x = COEFF_VAR, y = MISS_BMA.F2)) +
geom_point(shape = 1) +
geom_hline(yintercept = 0.25, linetype = "dashed", color = "darkred", size = 0.75) +
theme_standard
m3b <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, cols=2)

Flag LQ individuals.
Remove flagged loci and individuals.
Compare stats post-filtering:
# load stats files ----
ind_stats_F3 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F3") %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)
loc_stats_F3 <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.F3")
# plot missing data per indv ----
p1 <- ggplot(ind_stats_F3, aes(x = MISS_BMA.F3)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "missing data per indv") +
theme_standard
# plot read depth per indv ----
p2 <- ggplot(ind_stats_F3, aes(x = MEAN_DEPTH_BMA.F3)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per indv") +
theme_standard
# plot depth vs missing ----
p3 <- ggplot(ind_stats_F3, aes(x = MEAN_DEPTH_BMA.F3, y = MISS_BMA.F3)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per indv", y = "% missing data") +
theme_standard
# plot distribution missing data per locus ----
p4 <- ggplot(loc_stats_F3, aes(x = MISS_BMA.F3)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "% missing data per locus") +
theme_standard
# plot distribution mean read depth ----
p5 <- ggplot(loc_stats_F3, aes(x = MEAN_DEPTH_BMA.F3)) +
geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per locus") +
theme_standard
# plot read depth vs missing data ----
p6 <- ggplot(loc_stats_F3, aes(x = MEAN_DEPTH_BMA.F3, y = MISS_BMA.F3)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "% missing data") +
theme_standard
m3 <- multiplot(p1, p2, p3, p4, p5, p6, cols=2)

Filter 4: Allele balance
AB: Allele balance at heterozygous sites: a number between 0 and 1 representing the ratio of reads showing the reference allele to all reads, considering only reads from individuals called as heterozygous
Allele balance is the ratio of reads for reference allele to all reads, considering only reads from individuals called as heterozygous. Values range from 0 - 1; allele balance (for real loci) should be approx. 0.5. Filter SNPs for which the with allele balance < 0.25 and > 0.75.
read.table("data/VCF/temp/BMA.F4.AB",
col.names = "AB", stringsAsFactors = FALSE) %>%
ggplot(aes(x = AB)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(xintercept = 0.5, color = "red", linetype = "dashed", size = 1) +
geom_vline(xintercept = 0.25, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 0.75, color = "darkblue", linetype = "dashed", size = 1) +
theme_standard

Filter contigs with SNP calls with AB > 0.25, AB > 0.75; retain loci very close to 0 (retain loci that are fixed variants). Remove genotypes if the quality sum of the reference or alternate allele was 0.
Remaining SNPs: 52,610.
Filter 5: quality/depth ratio
Compare quality/depth ratio.
# depth
depth <- read.table("data/VCF/temp/BMA.4.DEPTH",
col.names = "depth")
# quality score
qual <- read.table("data/VCF/temp/BMA.F4.loci.qual",
col.names = c("locus", "pos", "qual"))
temp <- bind_cols(qual, depth) %>%
mutate(ratio = qual/depth)
ggplot(temp, aes(x = ratio)) +
geom_histogram(binwidth = 0.25, color = "black", fill = "grey85") +
geom_vline(xintercept = 0.2, color = "darkred", linetype = "dashed", size = 1) +
theme_standard

Remove loci with quality/depth ratio < 0.2
Remaining SNPs: 31,880.
Filter 6: mapping quality
Remove loci based on ratio of mapping quality for reference and alternate allele, i.e. sites that have a high discrepancy between the mapping qualities of two alleles.
temp <- read.table("data/VCF/temp/BMA.F5.MQM", col.names = "MQM")
mapqual <- read.table("data/VCF/temp/BMA.F5.MQMR", col.names = "MQMR")
mapqual <- bind_cols(mapqual, temp) %>%
mutate(ratio = MQM/MQMR)
filter <- mapqual %>%
filter(ratio < 0.25 | ratio > 1.75)
ggplot(mapqual, aes(x = MQM, y = MQMR)) +
geom_point(shape = 1, size = 1) +
geom_abline(intercept = 0, slope = 1, size = 1, color = "red", linetype = "dashed") +
geom_abline(intercept = 0, slope = 4, size = 1, color = "darkblue", linetype = "dashed") +
geom_abline(intercept = 0, slope = 0.571, size = 1, color = "darkblue", linetype = "dashed") +
geom_point(data = filter, aes(x = MQM, y = MQMR), shape = 21, color = "black", fill = "red") +
scale_x_continuous(limits = c(0, 65)) +
scale_y_continuous(limits = c(0, 65)) +
theme_standard

Filter loci with mapping quality ratio < 0.25 and > 1.75.
Remaining SNPs: 30,183.
Filter 7: Strand balance
SRF: Number of reference observations on the forward strand SAF: Number of alternate observations on the forward strand SRR: Number of reference observations on the reverse strand SAR: Number of alternate observations on the reverse strand
Paired end reads should not overlap, and a SNP site should only be covered by either the forward or reverse read (strand).
SAF <- read.table("data/VCF/temp/BMA.F6.SAF",
col.names = "SAF")
SAR <- read.table("data/VCF/temp/BMA.F6.SAR",
col.names = "SAR")
strands <- bind_cols(SAF, SAR)
SRF <- read.table("data/VCF/temp/BMA.F6.SRF",
col.names = "SRF")
strands <- bind_cols(strands, SRF)
SRR <- read.table("data/VCF/temp/BMA.F6.SRR",
col.names = "SRR")
strands <- bind_cols(strands, SRR) %>%
mutate(ratioA = SAF/SAR, ratioR = SRF/SRR)
ggplot(strands, aes(x = SAF, y = SAR)) +
geom_point(shape = 1) +
geom_abline(intercept = 0, slope = 0.1, color = "darkblue", linetype = "dashed", size = 1) +
geom_abline(intercept = 0, slope = 100, color = "darkblue", linetype = "dashed", size = 1) +
theme_standard

Remove SNP sites that have > 100x more forward alternate reads than reverse alternate reads and > 100x more forward reverse reads than reverse alternate reads.
Number of SNPs remaining: 26,722.
Filter 8: Properly paired status
PAIRED: Proportion of observed alternate alleles which are supported by properly paired read fragments PAIREDR: Proportion of observed reference alleles which are supported by properly paired read fragments
Identify loci with only unpaired reads mapping to them - an artifact introduced due de novo reference assembly. Compare number of paired reads mapping the reference and the alternate alleles to identify discrepancy in the paired status for reads supporting reference and alternate alleles.
Number of SNPs in data set: 23,778.
Filter 9: Maximum depth & Quality
Identify distribution of depth (based on original data set) to identify loci with excess coverage.
Original number of individuals in data set is 424 (INFO flags in filtered data set are are based on original number of individuals in data set).
Create file with the original site depth and quality score for each site:
Calculate average depth and standard deviation:
# depth
depth <- read.table("data/VCF/temp/BMA.F8.DEPTH",
col.names = "depth")
# quality score
qual <- read.table("data/VCF/temp/BMA.F8.loci.qual",
col.names = c("locus", "pos", "qual"))
# mean depth
mean_depth <- mean(depth$depth)
# standard deviation
std <- sd(depth$depth)
# calculate cutoff
cutoff <- sum(mean_depth + (2*std))
# identify SNPs with excess (i.e. depth > mean depth + 1 standard deviation
# and quality score < 2x the depth at that site
df <- bind_cols(qual, depth) %>%
mutate(qualcutoff = 2*depth)
removeloc <- df %>%
filter(depth > cutoff) %>%
filter(qual < 2*depth)
# plot
ggplot(df, aes(x = depth, y = qual)) +
geom_point(shape = 1) +
geom_point(data = removeloc, aes(x = depth, y = qual), shape = 21, color = "black", fill = "red") +
geom_line(data = df, aes(x = depth, y = qualcutoff), color = "blue", linetype = "dashed", size = 1) +
geom_vline(xintercept = cutoff, color = "blue", linetype = "dashed", size = 1) +
theme_standard

Mean depth per locus (across all indivuals) is 3.867019810^{4} and the standard deviation is 4.218984410^{4}.
Filter SNP site with depth > mean depth + 1 standard deviation = 1.230498910^{5} and that have quality scores < 2x the depth at that site and output depth per site.
Compare the distribution of mean depth per site averaged across individuals to determine cut-off value of sites with excessively high depth indicative of paralogs/multicopy loci.
# calculate mean depth per site (177 individuals)
read.table("data/VCF/BMA.F9a.ldepth.mean",
header = TRUE, stringsAsFactors = FALSE) %>%
ggplot(aes(x = MEAN_DEPTH)) +
geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = quantile(MEAN_DEPTH, .95)),
color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = quantile(MEAN_DEPTH, .99)),
color = "darkblue", linetype = "dashed", size = 1) +
scale_y_sqrt() +
labs(x = "mean depth per site") +
theme_standard

Choose cut-off for maximum mean read depth = 300.
Depth distribution per locus after filtering:

Analyze stats post-filtering:
# load stats files ----
ind_stats_F9 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F9") %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)
loc_stats_F9 <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.F9")
# plot missing data per indv ----
p1 <- ggplot(ind_stats_F9, aes(x = MISS_BMA.F9)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "missing data per indv") +
theme_standard
# plot read depth per indv ----
p2 <- ggplot(ind_stats_F9, aes(x = MEAN_DEPTH_BMA.F9)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per indv") +
theme_standard
# plot depth vs missing ----
p3 <- ggplot(ind_stats_F9, aes(x = MEAN_DEPTH_BMA.F9, y = MISS_BMA.F9)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per indv", y = "% missing data") +
theme_standard
# plot distribution missing data per locus ----
p4 <- ggplot(loc_stats_F9, aes(x = MISS_BMA.F9)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "% missing data per locus") +
theme_standard
# plot distribution mean read depth ----
p5 <- ggplot(loc_stats_F9, aes(x = MEAN_DEPTH_BMA.F9)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per locus") +
theme_standard
# plot read depth vs missing data ----
p6 <- ggplot(loc_stats_F9, aes(x = MEAN_DEPTH_BMA.F9, y = MISS_BMA.F9)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "% missing data") +
theme_standard
m3 <- multiplot(p1, p2, p3, p4, p5, p6, cols=2)

Data set contains 23040 SNP sites and 402 individuals.
Filter 10: Missing data and minimum depth per locus
Filter loci with mean read depth < 15 and genotype call rate < 90%.
Filter 11: Excess heterozygosity
Identify SNPs with more than 0.5 heterozygosity and significant.
# calculate observed heterozygosity
hwe <- read.table("data/VCF/BMA.F10.hwe",
stringsAsFactors = FALSE, header = TRUE) %>%
select(-ChiSq_HWE) %>%
separate(`OBS.HOM1.HET.HOM2.`,
into = c("obs_hom1", "obs_het", "obs_hom2"),
sep = "/", convert = TRUE) %>%
separate(`E.HOM1.HET.HOM2.`,
into = c("exp_hom1", "exp_het", "exp_hom2"),
sep = "/", convert = TRUE) %>%
mutate(Ho = obs_het/(obs_hom1 + obs_hom2 + obs_het),
He = exp_het/(exp_hom1 + exp_hom2 + exp_het)) %>%
select(CHR, POS, obs_hom1, exp_hom1, obs_hom2, exp_hom2, P_HET_DEFICIT, obs_het, exp_het, P_HET_EXCESS, Ho, He, P_HWE)
Distribution of observed heterozygosity.

Identify loci with heterozygosity > 0.5, then correct p-values for multiple comparisons using Benjamini-Hochberg method.
Remove SNPs with excess heterozygosity and contigs with more than one SNP w/excess heterozygosity.
Visualize stats:
Data set contains 16831 SNP sites and 402 individuals.
Filter 12: Filter LQ individuals
Compare mean depth and number of sites called per individual.

Use genotype depth file to identify individuals with high variance in read depth across loci.
# number of individuals
n <- nrow(ind_stats_F11)+1
# read genotype depth & code values < 5 as missing, retain only one locus per contig
gdepth <- read_table2("data/VCF/BMA.F11.gdepth") %>%
select(-POS) %>%
distinct(CHROM, .keep_all = TRUE) %>%
gather(key = INDV, value = GDEPTH, 2:n) %>%
mutate(GDEPTH = as.numeric(gsub(-1, 0, GDEPTH))) %>%
mutate(DEPTH = GDEPTH) %>%
mutate(DEPTH = as.numeric(gsub("\\<1\\>", 0, DEPTH))) %>%
mutate(DEPTH = as.numeric(gsub("\\<2\\>", 0, DEPTH))) %>%
mutate(DEPTH = as.numeric(gsub("\\<3\\>", 0, DEPTH))) %>%
mutate(DEPTH = as.numeric(gsub("\\<4\\>", 0, DEPTH))) %>%
mutate(MISSING = ifelse(DEPTH == 0, "missing", "genotyped")) %>%
mutate(GDEPTHBIN = cut(GDEPTH,
breaks = c(0, 5, 10, 25, 50, 100, 500, max(GDEPTH)),
labels = c("<5", "3-10", "10-25", "25-50", "50-100", "100-500", ">500"))) %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE, extra = "merge") %>%
mutate(LIB = str_replace_all(LIB, "1A.*", "BMA1"),
LIB = str_replace_all(LIB, "1B.*", "BMA1"),
LIB = str_replace_all(LIB, "2A.*", "BMA2"),
LIB = str_replace_all(LIB, "2B.*", "BMA2"),
LIB = str_replace_all(LIB, "3A.*", "BMA3"),
LIB = str_replace_all(LIB, "3B.*", "BMA3"))
gdepth <- left_join(gdepth, SampleInfo, by = "SAMPLE_ID")
Compare distribution of depth.
# would need to join with Sample Info to get pop specifications
ggplot(gdepth, aes(x = INDV, y = CHROM)) +
geom_tile(aes(fill = GDEPTHBIN)) +
scale_fill_viridis(direction = -1, option = "viridis",
name = 'genotype depth',
discrete = TRUE) +
facet_grid(. ~ POP, space = "free", scales = "free", drop = TRUE) +
labs(x = "individual", y = "locus") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
legend.position = "bottom")

Compare distribution of depth of individuals grouped by library.
ggplot(gdepth, aes(x = INDV, y = CHROM)) +
geom_tile(aes(fill = GDEPTHBIN)) +
scale_fill_viridis(direction = -1, option = "viridis",
name = 'genotype depth',
discrete = TRUE) +
facet_grid(. ~ LIB, space = "free", scales = "free", drop = TRUE) +
labs(x = "individual", y = "locus") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
legend.position = "bottom")

Compare distribution of genotype depths (across all individuals).

Identify variance in depth w/in individuals.
# calculate summary statistics
idepth <- gdepth %>%
group_by(INDV) %>%
summarize(TOTAL = sum(DEPTH),
MAX = max(DEPTH),
MEAN = mean(DEPTH),
MEDIAN = median(DEPTH),
VAR = var(DEPTH),
STD = sd(DEPTH)) %>%
mutate(COEFF_VAR = STD/MEAN,
RATIO_MEAN_MEDIAN = MEAN/MEDIAN)
p1 <- ggplot(idepth, aes(x = MEAN, y = MEDIAN)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p2 <- ggplot(idepth, aes(x = MAX, y = TOTAL)) +
geom_smooth(method = "lm",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p3 <- ggplot(idepth, aes(x = TOTAL, y = VAR)) +
geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
geom_point(shape = 1) +
theme_standard
p4 <- ggplot(idepth, aes(MEDIAN)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
theme_standard
p5 <- ggplot(idepth, aes(RATIO_MEAN_MEDIAN)) +
geom_histogram(binwidth = 0.1, color = "black", fill = "darkorange") +
theme_standard
p6 <- ggplot(idepth, aes(COEFF_VAR)) +
geom_histogram(binwidth = 0.05, color = "black", fill = "darkorange") +
theme_standard
m14b <- multiplot(p1, p2, p3, p4, p5, p6, cols=2)

Compare depth, missing data and individual heterozygosity levels.
imiss <- read_table2("data/VCF/BMA.F11.imiss") %>%
select(INDV, N_DATA, F_MISS)
istats <- left_join(idepth, imiss)
Fis <- read_table2("data/VCF/BMA.F11.het") %>%
select(-N_SITES)
istats <- left_join(istats, Fis)
p1 <- ggplot(istats, aes(x = MEAN, y = F_MISS, fill = `F`)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = 1, option = "viridis",
name = 'Fis', discrete = FALSE) +
theme_standard
p2 <- ggplot(istats, aes(x = COEFF_VAR, y = MEAN, fill = F_MISS)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = -1, option = "viridis",
name = '% missing', discrete = FALSE) +
theme_standard
p3 <- ggplot(istats, aes(x = `O(HOM)`, y = MEAN, fill = F_MISS)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = -1, option = "viridis",
name = 'mean read depth', discrete = FALSE) +
theme_standard
p4 <- ggplot(istats, aes(x = MEAN)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
theme_standard
p5 <- ggplot(istats, aes(x = `F`, y = MEAN, fill = F_MISS)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = -1, option = "viridis",
name = '% missing', discrete = FALSE) +
theme_standard
p6 <- ggplot(istats, aes(x = `F`, y = COEFF_VAR, fill = F_MISS)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = -1, option = "viridis",
name = '% missing', discrete = FALSE) +
theme_standard
p7 <- ggplot(istats, aes(x = `F`, y = RATIO_MEAN_MEDIAN, fill = F_MISS)) +
geom_point(shape = 21, size = 2, color = "black") +
scale_fill_viridis(direction = -1, option = "viridis",
name = '% missing', discrete = FALSE) +
scale_y_continuous(limits = c(0.8, 4)) +
theme_standard
p8 <- ggplot(istats, aes(x = F_MISS)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
theme_standard
m14b <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, cols=2)

Flag low quality individuals
Filter 13: Missing data by sample location
Compare missing data per sample region:
# pops to loop over
pop <- unique(Ind_RAW$POP)
loc_missing <- list()
# import missing data per locus
for (p in pop) {
loc_missing[[p]] <- read_delim(paste("data/VCF/", p, ".lmiss", sep = ""), delim = "\t") %>%
select(CHR, POS, F_MISS) %>%
mutate(POP = p)
}
# create data frame with all information
loc_missing <- ldply(loc_missing, data.frame)
ggplot(loc_missing, aes(x = F_MISS)) +
geom_histogram(binwidth = .05, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = 0.15),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "missing data per locus") +
scale_y_sqrt() +
facet_grid(POP ~ .) +
theme_standard

identify loci with high missing data in each sample location (> 15 % missing data in a given location).
Remove loci from data set:
Compare stats:
# load stats files ----
ind_stats_F13 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F13") %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE, extra = "merge")
loc_stats_F13 <- read.loc.stats(dir = "data/VCF", vcf = "BMA.F13")
# plot missing data per indv ----
p1 <- ggplot(ind_stats_F13, aes(x = MISS_BMA.F13)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "missing data per indv") +
theme_standard
# plot read depth per indv ----
p2 <- ggplot(ind_stats_F13, aes(x = MEAN_DEPTH_BMA.F13)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per indv") +
theme_standard
# plot depth vs missing ----
p3 <- ggplot(ind_stats_F13, aes(x = MEAN_DEPTH_BMA.F13, y = MISS_BMA.F13)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per indv", y = "% missing data") +
theme_standard
# plot Fis per indv ----
p4 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv") +
theme_standard
# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13, y = MISS_BMA.F13)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "% missing data") +
theme_standard
# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13, y = MEAN_DEPTH_BMA.F13)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "mean depth per indv") +
theme_standard
# plot distribution missing data per locus ----
p7 <- ggplot(loc_stats_F13, aes(x = MISS_BMA.F13)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "% missing data per locus") +
theme_standard
# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_F13, aes(x = MEAN_DEPTH_BMA.F13)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per locus") +
theme_standard
# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_F13, aes(x = MEAN_DEPTH_BMA.F13, y = MISS_BMA.F13)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "% missing data") +
theme_standard
# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA.F13.lqual",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(PROB = 10^(-QUAL/10))
temp <- data.frame(loc_stats_F13$MEAN_DEPTH_BMA.F13, site_qual$QUAL) %>%
rename(depth = loc_stats_F13.MEAN_DEPTH_BMA.F13, qual = site_qual.QUAL)
p10 <- ggplot(temp, aes(x = depth, y = qual)) +
geom_point(size = 1) +
geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "SNP quality") +
theme_standard
# plot number of SNPs per contig vs. mean depth ----
temp <- loc_stats_F13 %>%
count(CHR)
p11 <- left_join(temp, loc_stats_F13) %>%
ggplot() +
geom_point(aes(x = n, y = MEAN_DEPTH_BMA.F13)) +
labs(x = "number of SNPs per contig", y = "mean depth") +
theme_standard
# plot no of SNPs per locus ----
p12 <- loc_stats_F13 %>%
count(CHR) %>%
ggplot(aes(x = n)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
labs(x = "number of SNPs per locus") +
theme_standard
m15 <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

Compare number of contigs vs number of SNPs.
[1] 14682
[1] 6048
Mean number of SNPs per contig is 64.1135371.
Final thresholds values for filtered data set BMA:
- minimum sequence quality (minQ): 20
- minimum genotype quality (minGQ): 20
- minimum genotype call rate per locus (geno): 90%
- minimum genotype depth (minD): 5
- maximum missing data per individual (missInd): 25%
- mean minimum depth per locus (m-minD): 15
- mean maximum depth (m-minD): 300
- dDocent filters run for allelic balance, mapping quality, strandedness and paired status, depth/quality ratio
- Indels removed from data set
- minimum genotype call rate by population: 85%
Data set contains 14682 SNP sites on 229 and 384 individuals.
Haplotyping
Prep for haplotyping
Create list of individuals retained in final vcf file:
Change so that new file is printed into Haplotyping/temp folder
Use BMA-BMA.individuals to create popmap as a tab-separated file of individuals and their population designation, with one individual per line (make sure UNIX format). This file is needed to write the genepop file, if not provided the script will run through the process but not write a genepop file and place into same folder rad_haplotyper.pl will be run from.
popmap <- read.table("data/Haplotyping/temp/BMA.individuals",
col.names = "INDV", stringsAsFactors = FALSE) %>%
separate(INDV, into = c("POP", "LIB", "ID"), sep = "_", remove = FALSE, extra = "merge") %>%
select(INDV, POP)
write.table(popmap, "data/Haplotyping/temp/popmap",
col.names = FALSE, row.names = FALSE, quote = FALSE)
Place all necessary files in data/Haplotyping/temp directory (bam, fastq, reference.fasta, vcf-file)
Run Haplotyper
Copy files for analysis into data/Haplotyping/-folder
Haplotype filtering
Overview of haplotyping success
Comparison of the number of loci that were filtered due to excess number of missing data or suspected paralogs during the haplotyping process to those that passed. Haplotyer was run without any threshold values (other than default values). The genepop file only contains loci that passed haplotyping stage.

Remove filtered loci from data set.
5957 loci passed haplotyping process.

Data set contains 384 individuals:

Identify threshold values to filter data set
Proportion of individuals haplotyped
# hap_stats <- read.hap.stats("data/Haplotyping/stats.out")
p1 <- ggplot(hap_stats, aes(x = Prop_Haplotyped)) +
geom_histogram(binwidth = 0.025, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Prop_Haplotyped, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.9),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "proportion individuals haplotyped") +
theme_standard
p2 <- ggplot(hap_stats, aes(x = Prop_Haplotyped, y = Poss_Paralog)) +
geom_point(shape = 21, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Prop_Haplotyped, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "proportion individuals haplotyped", y = "possible paralogs") +
theme_standard
p3 <- ggplot(hap_stats, aes(x = Prop_Haplotyped, y = `Low_Cov.Geno_Err`)) +
geom_point(shape = 21, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Prop_Haplotyped, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "proportion individuals haplotyped", y = "low coverage error") +
theme_standard
multiplot(p1, p2, p3, cols = 3)

Flag loci successfully haplotyped in < 90% of individuals.
136 loci were flagged as genotype call rate < 0.9.
Possible paralogs per locus
Loci are flagged as possible paralogs for an individuals when more than the expected number of haplotypes based on the SNP genotype call (homozygote, heterozygote) are detected.
ggplot(hap_stats, aes(x = Poss_Paralog)) +
geom_histogram(binwidth = 2, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Poss_Paralog, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = (nrow(hap_ind_stats)*0.01)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "possible paralogs per locus") +
theme_standard

1 % of individuals: 3.84 5 % of individuals: 19.2
Flag loci that are flagged as potential paralogs in 5 or more individuals. 4
176 loci were flagged as possible paralogs.
Number of SNPs & Haplotypes per locus
Each locus varies in the number of SNPs detected which determines the number of haplotypes expected in that population.
ggplot(hap_stats, aes(x = Sites)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Sites, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "number of SNPs per contig") +
theme_standard

Filtering loci based on number of SNPs contained on that locus could bias the data set as loci with high recombination may be removed. On the other hand, assuming an approximate length of 250 bp loci with more than 25 SNPs would mean that 10% of bases are a polymorphisms.
p1 <- ggplot(hap_stats, aes(x = Haplotypes, y = Poss_Paralog)) +
geom_point(shape = 21, color = "black", fill = "darkorange") +
geom_smooth(method = "lm") +
labs(x = "no. haplotypes", y = "possible paralogs") +
theme_standard
p2 <- ggplot(hap_stats, aes(x = Sites, y = Poss_Paralog)) +
geom_point(shape = 21, color = "black", fill = "darkorange") +
geom_smooth(method = "lm") +
labs(x = "no. of sites", y = " ") +
theme_standard
multiplot(p1, p2, cols = 2)

Identify number of haplotypes loci with > 35 SNP sites.
0 loci were flagged.
Assuming that mutation is the only mechanism resulting in new haplotypes, the maximum expected number of haplotypes per locus is number of SNPs N + 1.
p1 <- ggplot(hap_stats, aes(x = Haplotypes)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Haplotypes, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = quantile(Haplotypes, .99, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
labs(x = "# haplotypes per locus", y = "# loci") +
theme_standard
temp <- hap_stats %>%
select(Locus, Sites, Haplotypes, Prop_Haplotyped, Low_Cov.Geno_Err, Poss_Paralog) %>%
mutate(exp_sites = Sites + 1) %>%
mutate(xtra = Haplotypes - Sites)
p2 <- ggplot(temp, aes(x = Sites, y = Poss_Paralog)) +
geom_point() +
geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# SNP sites per locus", y = "possible paralogs") +
theme_standard
p3 <- ggplot(temp, aes(x = Sites, y = xtra)) +
geom_point() +
geom_hline(yintercept = 10, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# SNP sites per locus", y = "# extra haplotypes") +
theme_standard
p4 <- ggplot(temp, aes(x = xtra, y = Prop_Haplotyped)) +
geom_point(size = 1) +
geom_hline(yintercept = 0.9, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# extra haplotypes", y = "proportion of indv haplotyped") +
theme_standard
p5 <- ggplot(temp, aes(x = xtra, y = Low_Cov.Geno_Err)) +
geom_point(size = 1) +
geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# extra haplotypes", y = "potential genotyping error") +
theme_standard
p6 <- ggplot(temp, aes(x = xtra, y = Poss_Paralog)) +
geom_point(size = 1) +
geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# extra haplotypes", y = "possible paralogs") +
theme_standard
m21 <- multiplot(p1, p2, p3, p4, p5, p6, cols = 2)

Again, removing loci with unexpectedly high numbers of haplotypes may bias the data set, as loci with e.g. high recombination may be removed from the data set.
0 loci were flagged for excessive number of haplotypes compared to the number of SNPs at that locus.
Low Coverage/Genotyping Error
After combining SNPs on the same contig during the haplotyping process, it is possible to observe fewer than the expected number of haplotypes based on the genotype call (heterozygote/homozygote). When this occurs, that genotype is coded as missing. For each locus the number of individuals for which is it flagged as a potential a potential genotyping error or suffering from null alleles due to low coverage detected for a given locus is recorded.
ggplot(hap_stats, aes(x = Low_Cov.Geno_Err)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Low_Cov.Geno_Err, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = (nrow(hap_ind_stats)*0.05)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "potential genotyping error") +
theme_standard

Loci with pronounced patterns of genotyping error likely due to low coverage will have low success rate for genotyping, i.e. they will be caught in missing data filters. Coverage issues are likely genotype specfic; previous filters have targeted loci and individuals with high variance in coverage and suspect genotpes have been coded as missing, i.e. this filter need not be very conservative, regardless, loci that are repeatedly being flagged as problematic should be removed.
183 loci were flagged as potentially affected by genotyping error.
Flag problematic individuals
Loci that are not successfully haplotyped in an individual due to missing data, complex locus, haplotyped genotype is higher/lower than SNP haplotype in a given individual are coded as missing for that individual. Problematic individual can be identified as having a high proportion of missing data.
Individuals with low proportion of successfully haplotyped loci
ggplot(hap_ind_stats, aes(x = Prop_Success)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Prop_Success, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.75),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "proportion loci successfully haplotyped") +
theme_standard

Problem individuals can be identified by choosing a cut-off value for the minium proportion of sucessfully haplotyped loci and excluding individuals below that threshold value. Removing loci with low haplotyping success with decrease the amount of missing data. Therefore, final missing data cut-offs should be applied after removing those loci from the data set, though it is important to flag potentially problematic individuals based on their haplotyping stats at this point.
Possible paralogs per individual
Individuals with high proportion of loci flagged as possible paralogs should be flagged as potential problem individuals.
ggplot(hap_ind_stats, aes(x = Poss_Paralogs)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Poss_Paralogs, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = (nrow(hap_stats)*0.01)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "no of loci potential paralogs") +
theme_standard

Cut-off for individuals with loci flagged paralogs in > 1% of loci is 59.57.
The highest number of flagged loci in an individuals is 81, which is equivalent to 1.36% of loci.
Individuals with high proportion of potential allele dropout/genotyping error
ggplot(hap_ind_stats, aes(x = Low_Coverage.Errors)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Low_Coverage.Errors, na.rm = TRUE)),
color = "darkred", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = (nrow(hap_stats)*0.01)),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "# loci potential genotyping error", y = "# indv") +
theme_standard

Remove individuals with high proportion of loci that have been flagged as potential allele dropouts/genotyping error.
The highest number of flagged loci in an individuals is 110, which is equivalent to 1.85% of loci.
Filter flagged loci and individuals as necessary
Load genepop file with haplotyped loci.
Converting data from a Genepop .gen file to a genind object...
File description: BMA.gen
...done.
/// GENIND OBJECT /////////
// 384 individuals; 5,957 loci; 20,898 alleles; size: 35.6 Mb
// Basic content
@tab: 384 x 20898 matrix of allele counts
@loc.n.all: number of alleles per locus (range: 1-25)
@loc.fac: locus factor for the 20898 columns of @tab
@all.names: list of allele names for each locus
@ploidy: ploidy of each individual (range: 2-2)
@type: codom
@call: read.genepop(file = "data/Haplotyping/BMA.gen", ncode = 3L, quiet = FALSE)
// Optional content
@pop: population of each individual (group size range: 384-384)
Remove flagged loci and individuals.
# remove flagged loci
removeloc <- c(Poss_Paralogs, NoSNps, NoHaps, Geno_Err, Prop_Haplotyped)
gen <- genind.rem.loci(gen, removeloc)
# remove flagged individuals
removeInd <- c(Poss_ParalogInd, PropSuccessInd, GenoErrIndv,
"BMA_1A-H02_MS18", "BMA_1B-C05_MS-22", "BMA_1B-C03_MS-20", "BMA_3A-D01_BM006")
gen <- gen.ind.rem.Ind(gen, removeInd)
gen
/// GENIND OBJECT /////////
// 380 individuals; 5,621 loci; 18,801 alleles; size: 31.8 Mb
// Basic content
@tab: 380 x 18801 matrix of allele counts
@loc.n.all: number of alleles per locus (range: 1-25)
@loc.fac: locus factor for the 18801 columns of @tab
@all.names: list of allele names for each locus
@ploidy: ploidy of each individual (range: 2-2)
@type: codom
@call: .local(x = x, i = i, j = j, drop = drop)
// Optional content
@pop: population of each individual (group size range: 380-380)
Compare duplicate individuals
# extract genotype matrix
df <- genind2df(gen,
usepop = TRUE,
sep = ":", oneColPerAll = FALSE) %>%
select(-pop) %>%
rownames_to_column()
# create list of duplicates
pairs <- list()
# input each set of duplicates as a vector of a list
pairs[[1]] <- c("BMA_3B-E12_MS-37", "BMA_2A-C01_MS-57")
pairs[[2]] <- c("BMA_1A-C01_CCGN-001", "BMA_1A-D02_CCGN01")
pairs[[3]] <- c("BMA_1A-H04_CC02-35", "BMA_2B-B09_CC-35")
pairs[[4]] <- c("BMA_3B-H02_MS26", "BMA_3B-D01_MS26")
pairs[[5]] <- c("BMA_2B-H02_MB06", "BMA_1B-E06_MB-06")
pairs[[6]] <- c("BMA_1B-G11_CC-08", "BMA_1A-H03_CC02-08")
pairs[[7]] <- c("BMA_3B-H03_BM027", "BMA_3B-A07_BM027")
pairs[[8]] <- c("BMA_1B-C04_MS-21", "BMA_2A-C05_MS-61")
pairs[[9]] <- c("BMA_2B-H01_CS3", "BMA_1A-B03_CS-03")
pairs[[10]] <- c("BMA_3B-E11_MS-36", "BMA_1B-C12_MS-56")
pairs[[11]] <- c("BMA_2A-C07_MS-63", "BMA_1B-C06_MS-23")
pairs[[12]] <- c("BMA_2B-B01_CC-12", "BMA_3A-A02_CC-12")
pairs[[13]] <- c("BMA_2B-G05_BMAR-03", "BMA_3B-E12_BMAR-02")
# create empty list for genotype error (discordant loci)
genoerror <- list()
# create empty vector for duplicates (retains first indv in pair)
dup <- character()
# identify discordant genotypes for each set of duplicates
for (p in pairs){
# select duplicates from genotype matrix
geno <- df %>%
filter(rowname %in% p) %>%
select(-rowname)
# compare genotypes
comp <- (t(geno))
contigs <- as.data.frame(comp) %>%
rownames_to_column(var = "LOCUS") %>%
mutate(V1 = as.character(V1),
V2 = as.character(V2)) %>%
filter(V1 != V2)
# write vector with first individual in pair
ind <- p[1]
dup <- c(dup, ind)
genoerror[[ind]] <- contigs
}
# if it throws error object V1 or V2 not found it means one or more of the samples names are not correct or no longer in data set after filtering
# combine into one dataframe
genoerror <- ldply(genoerror, data.frame) %>%
rename(DUP1 = `.id`,
GENO_INDV1 = V1,
GENO_INDV2 = V2)
write_delim(genoerror, "results/haplotyped.genoerror", delim = "\t")
Compare genotype depth for discordant loci:
# import genotype depth keep one depth per contig
n <- nrow(ind_stats_F13) + 1
gdepth <- read_table2("data/VCF/BMA.F13.gdepth") %>%
select(-POS) %>%
distinct(CHROM, .keep_all = TRUE) %>%
gather(key = INDV, value = GDEPTH, 2:n) %>%
rename(LOCUS = CHROM)
# create dataframe with duplicates
dup_indv <- data.frame(matrix(ncol = 2, nrow = 0))
colnames(dup_indv) <- c("DUP1", "DUP2")
for (p in pairs){
p <- as.data.frame(t(p))
colnames(p) <- c("DUP1", "DUP2")
dup_indv <- bind_rows(dup_indv, p)
}
# add duplicate 2 to genoerror data frame
genoerror <- left_join(genoerror, dup_indv)
# add genotype depth information for duplicate 1
gdepth <- gdepth %>%
rename(DUP1 = INDV)
genoerror <- left_join(genoerror, gdepth) %>%
rename(GDEPTH1 = GDEPTH)
# add genotype depth information for duplicate 2
gdepth <- gdepth %>%
rename(DUP2 = DUP1)
genoerror <- left_join(genoerror, gdepth) %>%
rename(GDEPTH2 = GDEPTH)
# identify homozygote vs heterozygote genotypes
genoerror <- genoerror %>%
separate(col = GENO_INDV1, into = c("GENO1a", "GENO1b"), sep = ":", remove = FALSE) %>%
separate(col = GENO_INDV2, into = c("GENO2a", "GENO2b"), sep = ":", remove = FALSE) %>%
mutate(GENOTYPE1 = ifelse(GENO1a == GENO1b, "HOMOZYGOTE", "HETEROZYGOTE"),
GENOTYPE2 = ifelse(GENO2a == GENO2b, "HOMOZYGOTE", "HETEROZYGOTE"))
Determine number of times discordant genotype is due to heterozygote/homozygote.
Compare number of discordant genotype calls per duplicate set.

Identify loci consistently affected by genotyping error

Remove flagged loci and one individual per pair.
# write vector with second individual in pair (lower quality)
rm <- c("BMA_2A-C01_MS-57", "BMA_1A-D02_CCGN01", "BMA_2B-B09_CC-35", "BMA_3B-D01_MS26", "BMA_1B-E06_MB-06",
"BMA_1A-H03_CC02-08", "BMA_3B-A07_BM027", "BMA_2A-C05_MS-61", "BMA_1A-B03_CS-03", "BMA_1B-C12_MS-56",
"BMA_1B-C06_MS-23", "BMA_3A-A02_CC-12", "BMA_3B-E12_BMAR-02")
# remove duplicates
removeInd <- rm
gen <- gen.ind.rem.Ind(gen, removeInd)
# remove flagged loci
removeloc <- filter(per_loc, n > 3)
gen <- genind.rem.loci(gen, removeloc)
gen
/// GENIND OBJECT /////////
// 367 individuals; 5,621 loci; 18,801 alleles; size: 30.9 Mb
// Basic content
@tab: 367 x 18801 matrix of allele counts
@loc.n.all: number of alleles per locus (range: 1-25)
@loc.fac: locus factor for the 18801 columns of @tab
@all.names: list of allele names for each locus
@ploidy: ploidy of each individual (range: 2-2)
@type: codom
@call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)
// Optional content
@pop: population of each individual (group size range: 367-367)
12708 loci were removed as potentially affected by genotyping error.
Heterozygosity and HWE
Generate summary statistics
SampleInfo <- read_delim("data/POPGEN/SampleInfo.txt", delim = "\t") %>%
distinct(SAMPLE_ID, .keep_all = TRUE)
Inds <- as.data.frame(indNames(gen)) %>%
rename(LIB_ID = `indNames(gen)`) %>%
separate(LIB_ID, into = c("SP", "WELL", "SAMPLE_ID"), sep = "_", extra = "merge", remove = FALSE)
strata <- left_join(Inds, SampleInfo) %>%
distinct() %>%
mutate(POP = ordered(POP, levels = pops)) %>%
mutate(REGION = case_when(POP %in% c("FLA") ~ "SWATL",
POP %in% c("CAMP") ~ "SGULF",
POP %in% c("FLGS", "FLGN") ~ "EGULF",
POP %in% c("MB", "MISS", "CS", "LA") ~ "CGULF",
POP %in% c("CC") ~ "WGULF",),
OCEAN = ifelse(POP == "FLA", "ATL", "GULF"))
strata(gen) <- strata
# define groups using strata information - need to add POP for missing ones
setPop(gen) <- ~POP
# generate genetic diversity stats
GenDiv <- adegenet::summary(gen)
dat <- hierfstat:::.genind2hierfstat(gen)
GenDiv2 <- basic.stats(dat)
Compare observed (Ho) and expected (He) heterozygosity for all individuals across all populations.
Identify loci that are now monomorphic and remove from data set:
/// GENIND OBJECT /////////
// 367 individuals; 5,590 loci; 18,768 alleles; size: 30.9 Mb
// Basic content
@tab: 367 x 18768 matrix of allele counts
@loc.n.all: number of alleles per locus (range: 2-25)
@loc.fac: locus factor for the 18768 columns of @tab
@all.names: list of allele names for each locus
@ploidy: ploidy of each individual (range: 2-2)
@type: codom
@call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)
// Optional content
@pop: population of each individual (group size range: 20-52)
@strata: a data frame with 5 columns ( LIB_ID, SP, WELL, SAMPLE_ID, POP )
Expected vs observed heterozygosity across all populations.

Compare distribution of observed heterozygosity (Ho) in each putative population:

Compare distribution of expected heterozygosity He, (within cluster diversity) in each putative population:
# within cluster diversity/exp diversity per locus (rows) and cluster (columns)
Hs_per <- as.data.frame(GenDiv2$Hs) %>%
rownames_to_column("LOCUS") %>%
rename(CAMP = `1`, FLGS = `2`, FLGN = `3`, FLA = `4`, CS = `5`,
CC = `6`, MISS = `7`, LA = `8`, MB = `9`) %>%
select(LOCUS, CAMP, FLGS, FLGN, FLA, CS, CC, MISS, LA, MB) %>%
gather(Group, Hs, 2:9)
# compare expected heterozygosity per locus and cluster
ggplot(Hs_per, aes(x = Group, y = Hs)) +
geom_boxplot() +
labs(x = "Group", y = "expected heterozygosity Ho") +
theme_standard

Comparison of oberved vs. heterozygosity within each population:
# join data frames
Het_per <- left_join(Hs_per, Ho_per)
# plot per cluster
ggplot(Het_per, aes(x = Ho, y = Hs)) +
geom_point(shape = 19, size = 1) +
geom_abline(intercept = 0, slope = 1, color = "red", linetype = "dashed", size = 1) +
xlim(0, 1) +
ylim(0, 1) +
facet_grid(. ~ Group) +
labs(x = "observed heterozygosity Ho", y = "within cluster diversity Hs (Hexp)") +
theme_standard

Test for deviations from Hardy-Weinberg equilibrium within each group (POP level):
Format output and view results:

Distribution of number of times loci are out of HWE

Remove loci out of HWE in 5 or more populations:
/// GENIND OBJECT /////////
// 367 individuals; 5,554 loci; 18,611 alleles; size: 30.7 Mb
// Basic content
@tab: 367 x 18611 matrix of allele counts
@loc.n.all: number of alleles per locus (range: 2-25)
@loc.fac: locus factor for the 18611 columns of @tab
@all.names: list of allele names for each locus
@ploidy: ploidy of each individual (range: 2-2)
@type: codom
@call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)
// Optional content
@pop: population of each individual (group size range: 20-52)
@strata: a data frame with 7 columns ( LIB_ID, SP, WELL, SAMPLE_ID, POP, REGION, ... )
Final data set
Write files with filtered data set:
Write files with individuals and Contigs still contained in data set and use to filter vcf file.
keeploci <- as.data.frame(locNames(gen)) %>%
rename(LOCUS = `locNames(gen)`)
keeploci <- filter(loc_stats_F13, CHR %in% keeploci$LOCUS) %>%
select(CHR, POS)
write.table(keeploci, "data/VCF/filtered.loci",
col.names = FALSE, row.names = FALSE, quote = FALSE)
keepind <- as.data.frame(indNames(gen)) %>%
rename(LIB_ID = `indNames(gen)`) %>%
separate(LIB_ID, into = c("SP", "LIB", "WELL", "SAMPLE_ID"), sep = "-", extra = "merge") %>%
separate(SAMPLE_ID, into = c("P1", "P2"), sep = "-", remove = TRUE) %>%
unite(SAMPLE_ID, 4:5, sep = "_") %>%
unite(LIBWELL, 2:3, sep = "-") %>%
unite(LIB_ID, 1:3, sep = "_")
Expected 4 pieces. Missing pieces filled with `NA` in 329 rows [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, ...].Expected 2 pieces. Missing pieces filled with `NA` in 38 rows [10, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 163, 164, 165, 166, 167, 168, 169, 170, 171, ...].
Error in filter(ind_stats_F14, INDV %in% keepind$LIB_ID) :
object 'ind_stats_F14' not found
Write vcf file and 012 format:
Compare stats for final filtered data set:
# load stats files ----
ind_stats_fil <- read.ind.stats(dir = "data/VCF", vcf = "BMA.fil") %>%
separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)
loc_stats_fil <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.fil")
View(ind_stats_fil)
View(hap_ind_stats)
# plot missing data per indv ----
p1 <- ggplot(ind_stats_fil, aes(x = MISS_BMA.fil)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "missing data per indv") +
theme_standard
# plot Fis per indv ----
p2 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil)) +
geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv") +
theme_standard
# plot read depth per indv ----
p3 <- ggplot(ind_stats_fil, aes(x = MEAN_DEPTH_BMA.fil)) +
geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per indv") +
theme_standard
# plot depth vs missing ----
p4 <- ggplot(ind_stats_fil, aes(x = MEAN_DEPTH_BMA.fil, y = MISS_BMA.fil)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per indv", y = "% missing data") +
theme_standard
# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil, y = MISS_BMA.fil)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.25),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "% missing data") +
theme_standard
# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil, y = MEAN_DEPTH_BMA.fil)) +
geom_point() +
geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "Fis per indv", y = "mean depth per indv") +
theme_standard
# plot distribution missing data per locus ----
p7 <- ggplot(ind_stats_fil, aes(x = MISS_BMA.fil)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "% missing data per locus") +
theme_standard
# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_fil, aes(x = MEAN_DEPTH_BMA.fil)) +
geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean read depth per locus") +
theme_standard
# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_fil, aes(x = MEAN_DEPTH_BMA.fil, y = MISS_BMA.fil)) +
geom_point() +
geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 0.1),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "% missing data") +
theme_standard
# plot no of SNPs per locus ----
p10 <- loc_stats_fil %>%
count(CHR) %>%
ggplot(aes(x = n)) +
geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
labs(x = "number of SNPs per locus") +
theme_standard
temp <- loc_stats_fil %>%
count(CHR)
# plot number of SNPs per contig vs. mean depth ----
p11 <- left_join(temp, loc_stats_fil) %>%
ggplot() +
geom_point(aes(x = n, y = MEAN_DEPTH_BMA.fil)) +
labs(x = "number of SNPs per contig", y = "mean depth") +
theme_standard
# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA.fil.lqual",
header = TRUE, stringsAsFactors = FALSE) %>%
mutate(PROB = 10^(-QUAL/10))
temp <- data.frame(loc_stats_fil$MEAN_DEPTH_BMA.fil, site_qual$QUAL) %>%
rename(depth = loc_stats_fil.MEAN_DEPTH_BMA.fil, qual = site_qual.QUAL)
p12 <- ggplot(temp, aes(x = depth, y = qual)) +
geom_point(size = 1) +
geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
geom_hline(aes(yintercept = 20),
color = "darkblue", linetype = "dashed", size = 1) +
labs(x = "mean depth per locus", y = "SNP quality") +
theme_standard
mfil <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

LS0tCnRpdGxlOiAiR2Vub3R5cGluZyBHYWZmdG9wc2FpbCBjYXRmaXNoIGRhdGEgc2V0IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBoaWdobGlnaHQ6IGthdGUKICAgIHRoZW1lOiBmbGF0bHkKICAgIHRvYzogeWVzCi0tLQoKYGBge3IgbG9hZCBsaWJyYXJpZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cgpzb3VyY2UoInNjci9saWJyYXJpZXMuUiIpCnNvdXJjZSgic2NyL2dncGxvdC5SIikKc291cmNlKCJzY3IvVkNGZmlsdGVyc3RhdHMuUiIpCnNvdXJjZSgic2NyL0hhcGxvdHlwUi5SIikKc291cmNlKCJzY3IveHRyYWZ1bmN0aW9ucy5SIikKc291cmNlKCJzY3IvZ2VuaW5kLlIiKQoKCnBvcHMgPC0gYygiRkxBIiwgCiAgICAgICAgICAiRkxHUyIsICJGTEdOIiwgCiAgICAgICAgICAiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIsIAogICAgICAgICAgIkNDIiwgCiAgICAgICAgICAiQ0FNUCIpCgpjb2xfcG9wcyA8LSBjKCJjaGFydHJldXNlNCIsIAogICAgICAgICAgICAgICJkb2RnZXJibHVlNCIsICJzdGVlbGJsdWUxIiwgCiAgICAgICAgICAgICAgImZpcmVicmljayIsICJvcmFuZ2VyZWQzIiwgImRhcmtvcmFuZ2UiLCAiZ29sZCIsCiAgICAgICAgICAgICAgImRhcmtzbGF0ZWdyZXkxIiwKICAgICAgICAgICAgICAicHVycGxlMyIpCgpyZWcgPC0gYygiU1dBVEwiLCAiRUdVTEYiLCAiQ0dVTEYiLCAiV0dVTEYiLCAiU0dVTEYiKQoKY29sX3JlZ3MgPC0gYygiY2hhcnRyZXVzZTQiLCAiZG9kZ2VyYmx1ZTQiLCAib3JhbmdlcmVkMyIsICJkYXJrc2xhdGVncmF5MSIsICJwdXJwbGUzIikKCm9jZSA8LSBjKCJBVEwiLCAiR1VMRiIpCgpjb2xfb2NlIDwtIGMoImNoYXJ0cmV1c2U0IiwgImRhcmtzbGF0ZWdyYXkxIikKCmBgYAoKIyBSZWFkIG1hcHBpbmcKCiMjIE1hcCByZWFkcwoKQW55IHJlbmFtaW5nIG9mIGZpbGVzIG5lZWRzIHRvIGhhcHBlbiBiZWZvcmUgYGZhc3RxYC1maWxlcyBhcmUgbWFwcGVkLiBUaGUgcG9wdWxhdGlvbiBkZXNpZ25hdGlvbiAoYmVmb3JlIHVuZGVyc2NvcmUpIGlzIHVzZWQgYnkgYEZyZWVCYXllc2AgdG8gY2FsbCBTTlBzIHNvIGl0IGlzIGltcG9ydGFudCB0aGF0IHBvcHVsYXRpb24gZGVzaWduYXRpb24gbWFrZSBiaW9sb2dpY2FsIHNlbnNlLgoKVmFsdWVzIGNob3NlbiBmb3IgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2U6CgoqICoqYyoqID0gMC44CiogKipLMSoqID0gNQoqICoqSzIqKiA9IDIKClRyYW5zZmVyIGNvcHkgb2YgYHJlZmVyZW5jZS5mYXN0YWAgYW5kIGFzc29jaWF0ZWQgZmlsZXMgUmVmZXJlbmNlIGNvbnN0cnVjdGVkIHVzaW5nICpjID0gMC44KiwgKksxID0gNSosIGFuZCAqSzIgPSAyKi4gaW50byBlYWNoIGRpcmVjdG9yeSBjb250YWluaW5nIGRlbXVsdGlwbGV4ZWQgYW5kIHF1YWxpdHkgdHJpbW1lZCBkYXRhL1NFUQoKUnVuIGBkRG9jZW50YCBmcm9tIHdpdGhpbiBlYWNoIExpYnJhcnkgZGlyZWN0b3J5IHRvIG1hcCByZWFkcyB0byBgcmVmZXJlbmNlLmZhc3RhYC4KCmBgYHtiYXNofQoKIyBnbyB0byByZWZlcmVuY2UgcGFyZW50IGRpcmVjdG9yeQpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9TRVEvCgojIGxvb3Agb3ZlciBhbGwgcmVmZXJlbmNlIGNyZWF0aW9uIGZvbGRlcnMKZm9yIGQgaW4gQk1BKgoKZG8KCiAgICAoY3AgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvUkVGL1JFRjVfMi9yZWZlcmVuY2UuKiAkZC8pCiAgICAKZG9uZQoKYGBgCgpXcml0ZSBjb25maWd1cmF0aW9uIGZpbGUgdG8gcnVuIGREb2NlbnQgaW4gZWFjaCByZWZlcmVuY2UgZGlyZWN0b3J5LgoKYGBge3J9CgojIHBhcmFtZXRlcnMgZm9yIHNoZWxsIHNjcmlwdCAtLS0tCgojIGNvcnJlY3QgbnVtYmVyIG9mIGluZGl2aWR1YWxzCmluZCA8LSAieWVzIgoKIyBudW1iZXIgb2YgcHJvY2Vzc29ycwpwcm9jZXNzb3JzIDwtICIyNSIKCiMgcXVhbGl0eSB0cmltIG5lZWRlZAp0cmltIDwtICJubyIKCiMgcGVyZm9ybSByZWZlcmVuY2UgYXNzZW1ibHkKYXNzZW1ibHkgPC0gIm5vIgoKIyByZWFkIG1hcHBpbmcgcmVxdWlyZWQKbWFwIDwtICJ5ZXMiCgojIGN1c3RvbSB2YWx1ZXMgZm9yIG1hcHBpbmcKbWFwX3BhcmFtIDwtICJ5ZXMiCgojIG1hdGNoIHNjb3JlCkEgPC0gIjEiCgojIG1pc21hdGNoIHNjb3JlCkIgPC0gIjMiCgojIGdhcCBwZW5hbHR5Ck8gPC0gIjUiCgojIFNOUCBjYWxsaW5nIHJlcXVpcmVkCnNucCA8LSAibm8iCgojIGVtYWlsIGFkZHJlc3MKZW1haWwgPC0gInNoYW5ub24uai5vbGVhcnlAZ21haWwuY29tIgoKIyBkZWZpbmUgcGF0aHMvZGlyZWN0b3JpZXMgLS0tLQoKIyBwYXRoIHRvIHBhcmVudCBkaXJlY3RvcnkgZm9yIHJlZmVyZW5jZXMKcGF0aCA8LSAiL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRIgoKIyBzZXF1ZW5jZSBmb2xkZXJzCmRpciA8LSBjKCJCTUEtMSIsICJCTUEtMiIsICJCTUEtMyIpCgojIHdyaXRlIHNoZWxsIHNjcmlwdHMgaW4gZWFjaCBkaXJlY3RvcnkgLS0tLQpmb3IoZCBpbiBkaXIpewogIAogICMgd3JpdGUgc2hlbGwgc2NyaXB0CiAgcCA8LSBmaWxlLnBhdGgocGF0aCwgZCwgImREb2NlbnRfbWFwLnNoIikKICAKICBjb24gPC0gZmlsZShwLCBvcGVuID0gInd0IikKICAKICB3cml0ZUxpbmVzKGdsdWUoImREb2NlbnQgPDxPdmVyISAKICAgICAgICAgICAgICAgICAge2luZH0gCiAgICAgICAgICAgICAgICAgIHtwcm9jZXNzb3JzfSAKICAgICAgICAgICAgICAgICAge3RyaW19IAogICAgICAgICAgICAgICAgICB7YXNzZW1ibHl9IAogICAgICAgICAgICAgICAgICB7bWFwfSAgCiAgICAgICAgICAgICAgICAgIHttYXBfcGFyYW19IAogICAgICAgICAgICAgICAgICB7QX0gCiAgICAgICAgICAgICAgICAgIHtCfSAKICAgICAgICAgICAgICAgICAge099IAogICAgICAgICAgICAgICAgICB7c25wfSAKICAgICAgICAgICAgICAgICAge2VtYWlsfSAKICAgICAgICAgICAgICAgICAgT3ZlciEiKSwgY29uKQogIAogIGNsb3NlKGNvbikKICAKfQoKYGBgCgpFeGVjdXRlIGBkRG9jZW50YCBmcm9tIHdpdGhpbiBlYWNoIHJlZmVyZW5jZSBmb2xkZXIgdG8gaW5pdGlhdGUgYSBydW4gdG8gbWFwIGluZGl2aWR1YWxzIHRvIHJlZHVjZWQgcmVwcmVzZW50YXRpb24gcmVmZXJlbmNlIGFuZCBjYWxsIFNOUHMuCgpgYGB7YmFzaH0KCiMgZ28gdG8gc2VxdWVuY2UgcGFyZW50IGRpcmVjdG9yeQpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9TRVEvCgojIGxvb3Agb3ZlciBhbGwgcmVmZXJlbmNlIGNyZWF0aW9uIGZvbGRlcnMKZm9yIGQgaW4gQk1BLSoKCmRvCgogICAgKGNkICIkZCIgJiYgY2htb2QgNzU1IGREb2NlbnRfbWFwLnNoICYmIC4vZERvY2VudF9tYXAuc2gpCiAgICAKZG9uZQoKYGBgCgojIyBRQS9RQyByZWFkIG1hcHBpbmcKCiMjIyBRdWVyeSBtYXBwaW5nIHN0YXRpc3RpY3MKCkR1cmluZyB0aGUgbWFwcGluZyBzdGFnZSwgYGREb2NlbnRgIGNhbGxzIGBCV0FgIHRvIG1hcCByZWFkcyBmcm9tIHRoZSBpbmRpdmlkdWFscyBpbiB0aGUgZm9sZGVyIHRvIHRoZSBnZW5lcmF0ZWQgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2UgYW5kIGNyZWF0ZSBhIGAtUkcuYmFtYC1maWxlIGZvciBlYWNoIGluZGl2aWR1YWwuIFRoZSBzZWNvbmQgY29sdW1uIG9mIGEgQkFNIChvciBTQU0pIGZpbGUgY29udGFpbnMgRkxBR3Mgd2l0aCBiaW5hcnkgZW5jb2RlZCBpbmZvcm1hdGlvbiBvbiBtYXBwaW5nIHF1YWxpdHksIHBhaXJlZG5lc3MgZXRjLiB0aGF0IGNhbiBiZSB1c2VkIHRvIGNvbXBhcmUgdGhlIG1hcHBpbmcgZWZmaWNpZW5jeSB0byB0aGUgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2UuCgpUaGUgbnVtYmVyIG9mIHJlYWRzIG1hcHBlZCBjYW4gYmUgY291bnRlZCB1c2luZyBgc2FtdG9vbHMgaWR4c3RhdHMgPGFsbi1SRy5iYW0+YCB3aGljaCByZXRyaWV2ZXMgc3RhdHMgZnJvbSB0aGUgYmFtLWZpbGUuIFRoZSBvdXRwdXQgaXMgVEFCLWRlbGltaXRlZCBmaWxlIHdpdGggZWFjaCBsaW5lIGNvbnNpc3Rpbmcgb2YgdGhlIHJlZmVyZW5jZSBzZXF1ZW5jZSBuYW1lLCBzZXF1ZW5jZSBsZW5ndGgsICMgbWFwcGVkIHJlYWRzIGFuZCAjIHVubWFwcGVkIChlbXB0eSkgcmVhZHMuIEluIGFkZGl0aW9uLCBgc2FtdG9vbHNgIGNhbiBhbHNvIGJlIGJlIHVzZWQgdG8gcXVlcnkgYHNhbXRvb2xzIGZsYWdzdGF0IGZpbGUuYmFtYCB3aGljaCByZXR1cm5zIGFuIG91dHB1dCBjb250YWluaW5nIHRoZSBudW1iZXIgb2YgcmVhZHMgZm9yIHdoaWNoIGVhY2ggZmxhZyBpcyB0cnVlLgoKZERvY2VudCBjcmVhdGVzIGEgZmlsZSBjYWxsZWQgYGJhbWxpc3QubGlzdGAgY29udGFpbmluZyBhbGwgdGhlIGJhbSBmaWxlcyB0aGF0IHdlcmUgZ2VuZXJhdGVkIGR1cmluZyByZWFkIG1hcHBpbmcgaW4gYGREb2NlbnRgIHVzaW5nIGBCV0FgLiBXcml0ZSBzY3JpcHQgdG8gZ2F0aGVyIGZsYWdzdGF0cyBmcm9tIGFsbCBgYmFtYC1maWxlcy4KCmBgYHtyIGZsYWdzdGF0cyBzY3JpcHR9CgojIFNlcXVlbmNlIGZvbGRlcnMKU0VRIDwtIGMoIkJNQS0xIiwgIkJNQS0yIiwgIkJNQS0zIikKCiMgd3JpdGUgc2NyaXB0IHRvIGdhdGhlciBmbGFnc3RhdHMKbCA8LSBsaXN0KCkKCmZvciAocyBpbiBTRVEpewogIAogIGxbW3NdXSA8LSByZWFkX3RhYmxlMihwYXN0ZSgiZGF0YS9TRVEvIiwgcywgIi9iYW1saXN0Lmxpc3QiLCBzZXAgPSIiKSwgY29sX25hbWVzID0gIkJBTSIpICU+JQogICAgbXV0YXRlKFBBVEggPSBwYXN0ZSgiZGF0YS9TRVEvIiwgcywgIi8iLCBzZXAgPSAiIiksCiAgICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBmbGFnc3RhdCIsCiAgICAgICAgICAgT1VUID0gcGFzdGUoIj4+IGRhdGEvU0VRLyIsIHMsICIuZmxhZ3N0YXRzIiwgc2VwID0gIiIpKSAlPiUKICAgIHNlbGVjdCggQ09NTUFORCwgUEFUSCwgQkFNLCBPVVQpICU+JQogICAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCn0KCmJhbSA8LSBsZHBseShsLCBkYXRhLmZyYW1lKSAlPiUKICBzZWxlY3QoLWAuaWRgKQoKd3JpdGVfZGVsaW0oYmFtLCAic2NyL2ZsYWdzdGF0cy5zaCIsIGRlbGltID0gIlx0IiwgY29sX25hbWVzID0gRkFMU0UpCgpgYGAKClJ1biBmbGFnc3RhdHMuCgpgYGB7YmFzaCBydW4gZmxhZ3N0YXRzLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY2htb2QgNzU1IHNjci9mbGFnc3RhdHMuc2gKLi9zY3IvZmxhZ3N0YXRzLnNoCgpgYGAKCldyaXRlIHNjcmlwdCB0byBnYXRoZXIgaWR4c3RhdHMgZnJvbSBhbGwgYGJhbWAtZmlsZXMuCgpgYGB7ciBzY3JpcHQgaWR4c3RhdHN9CgojIHdyaXRlIHNjcmlwdCB0byBnYXRoZXIgaWR4c3RhdHMKbCA8LSBsaXN0KCkKCmxbWyJCTUExIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMS9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTEvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUExLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmxbWyJCTUEyIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMi9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTIvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUEyLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmxbWyJCTUEzIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMy9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTMvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUEzLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmJhbSA8LSBsZHBseShsLCBkYXRhLmZyYW1lKSAlPiUKICBzZWxlY3QoLWAuaWRgKQoKd3JpdGVfZGVsaW0oYmFtLCAic2NyL2lkeHN0YXRzLnNoIiwgZGVsaW0gPSAiXHQiLCBjb2xfbmFtZXMgPSBGQUxTRSkKCmBgYAoKUnVuIGluZHhzdGF0cy4KCmBgYHtiYXNoIHJ1biBpZHhzdGF0cywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCmNobW9kIDc1NSBzY3IvaWR4c3RhdHMuc2gKLi9zY3IvaWR4c3RhdHMuc2gKCmBgYAoKIyMjIEZvcm1hdCBzdGF0cyBmaWxlcyBpbnRvIHRpZHkgZGF0YSBzZXRzCgpBcHBlbmRpbmcgdGhlIGZpbGUgcmVzdWx0cyBpbiB0aGUgaW5mb3JtYXRpb24gcGVyIGluZGl2aWR1YWwgYmVpbmcgcHJpbnRlZCBpbiBhIG5ldyBzZXQgb2Ygcm93IGJlaW5nIGFwcGVuZGVkIHRvIHRoZSBmaWxlLCBpLmUuIHRoZXJlIHdpbGwgYmUgYXMgbWFueSByb3dzIGZvciBhIGdpdmVuIGxvY3VzIGFzIGluZGl2aWR1YWxzIHdlcmUgbWFwcGVkLiBUaGUgZmlsZSBjYW4gYmUgcmUtZm9ybWF0dGVkIGFuZCBzdW1tYXJ5IHN0YXRpc3RpY3MgY2FsY3VsYXRlZCB1c2luZyBkcGx5ciBhbmQgdGlkeXIuCgpGb3JtYXQgaWR4c3RhdHM6CgpgYGB7ciBmb3JtYXQgaWR4c3RhdHN9CgojIGNyZWF0ZSB2ZWN0b3JzIG9mIGZpbGVzIHRvIGJlIGltcG9ydGVkLCByZWZlcmVuY2UgY29kZXMsIEsxIGFuZCBLMiwgZGF0YWZyYW1lIG5hbWVzCmZpbGVuYW1lcyA8LSBsaXN0LmZpbGVzKHBhdGggPSAiZGF0YS9TRVEiLCBwYXR0ZXJuID0gIiouaWR4c3RhdHMiKQpuYW1lcyA8LSBzdWJzdHIoZmlsZW5hbWVzLCAxLCA4KQpsaWIgPC0gc3Vic3RyKGZpbGVuYW1lcywgMSwgNCkKCiMgaW1wb3J0IGRhdGEKZm9yIChpIGluIG5hbWVzKXsKICBmaWxlcGF0aCA8LSBmaWxlLnBhdGgoImRhdGEvU0VRIiwgcGFzdGUoaSwgJ3N0YXRzJywgc2VwID0iIikpCiAgYXNzaWduKGksIHJlYWQudGFibGUoZmlsZXBhdGgsIHNlcCA9ICIiLCBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiTG9jdXMiLCAiTGVuZ3RoIiwgIlJlYWRzX01hcHBlZCIsICdibGFuaycpKSAlPiUKICAgICAgICAgICBzZWxlY3QoMTozKSkKICB9CgojICMgbWFrZSBzdXJlIHRvIGRlbGV0ZSBvbGQgbGlzdCBpZiByZXJ1bm5pbmcgdGhlIGNvZGUKcm0oZGZsaXN0X2lkeCkKcm0oTWFwU3RhdHMuaWR4KQoKIyBDcmVhdGUgbGlzdCBvZiBvbmUgZGF0YWZyYW1lIHBlciBpZHhzdGF0cyBmaWxlIGFuZCBncm91cCBieSBsb2N1cwpkZmxpc3RfaWR4IDwtIGxhcHBseShscyhwYXR0ZXJuID0gIiouaWR4IiksIGdldCkKCmZvciAoZGYgaW4gMTpsZW5ndGgoZGZsaXN0X2lkeCkpewogIHggPC0gZGZsaXN0X2lkeFtbZGZdXQogIHhbWydMb2N1cyddXSA8LSBhcy5jaGFyYWN0ZXIoeFtbJ0xvY3VzJ11dKQogIHggPSB4ICU+JSBncm91cF9ieShMb2N1cykKICBkZmxpc3RfaWR4W1tkZl1dIDwtIHgKfQoKIyBDcmVhdGUgbmV3IGRhdGFmcmFtZXMgd2l0aCBzdW1tYXJ5IHN0YXRzIHBlciBsaWJyYXJ5IGFuZCBiaW5kIGludG8gZmluYWwgb3V0cHV0L2RhdGFmcmFtZQpNYXBTdGF0cy5pZHggPC0gZGF0YS5mcmFtZSgpCgpmb3IgKGRmIGluIDE6bGVuZ3RoKGRmbGlzdF9pZHgpKXsKICAgIAogIHggPSBzdW1tYXJpemUoZGZsaXN0X2lkeFtbZGZdXSwKICAgICAgICAgICAgICAgIExlbmd0aCA9IG1lYW4oTGVuZ3RoKSwKICAgICAgICAgICAgICAgIE1lYW5fTWFwcGVkID0gbWVhbihSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgU3VtX01hcHBlZCA9IHN1bShSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgTWluX01hcHBlZCA9IG1pbihSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgTWF4X01hcHBlZCA9IG1heChSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgU0RfTWFwcGVkID0gc2QoUmVhZHNfTWFwcGVkKSkKICB4W3ggPT0gMF0gPC0gTkEKCiAgdGVtcCA8LSBzdW1tYXJpemUoeCwgTWVhbl9NYXBwZWRfTm9uMCA9IG1lYW4oTWVhbl9NYXBwZWQsIG5hLnJtID0gVFJVRSkpICU+JQogICAgbXV0YXRlKExpYiA9IGxpYltkZl0sCiAgICAgICAgICAgTm90X01hcHBlZCA9IG5yb3coZmlsdGVyKHgsIGlzLm5hKFN1bV9NYXBwZWQpKSksCiAgICAgICAgICAgTl9Mb2NpX1JlZiA9IG5yb3coeCkpICU+JQogICAgc2VsZWN0KExpYiwgTl9Mb2NpX1JlZiwgTm90X01hcHBlZCwgTWVhbl9NYXBwZWRfTm9uMCkKCiAgTWFwU3RhdHMuaWR4IDwtIGJpbmRfcm93cyhNYXBTdGF0cy5pZHgsIHRlbXApCn0KCk1hcFN0YXRzLmlkeCA8LSBNYXBTdGF0cy5pZHggJT4lCiAgbXV0YXRlKFBST1BfRU1QVFkgPSByb3VuZCgoTm90X01hcHBlZC9OX0xvY2lfUmVmKSoxMDAsIGRpZ2l0cyA9IDIpLAogICAgICAgICBDT05USUdTX01BUFBFRCA9IE5fTG9jaV9SZWYgLSBOb3RfTWFwcGVkKQoKd3JpdGUudGFibGUoTWFwU3RhdHMuaWR4LCAicmVzdWx0cy9NYXBTdGF0cy5pZHgiLCBxdW90ZSA9IEZBTFNFKQoKIyByZW1vdmUgbGFyZ2UgKGR1cGxpY2F0ZSkgZmlsZXMKcm0oQk1BMS5pZHgpCnJtKEJNQTIuaWR4KQpybShCTUEzLmlkeCkKCk1hcFN0YXRzLmlkeAoKYGBgCgpGb3JtYXQgZmxhZ3N0YXRzOgoKYGBge3IgZm9ybWF0IGZsYWdzdGF0c30KCiMgRmlsZXMgdG8gYmUgaW1wb3J0ZWQKZmlsZW5hbWVzIDwtIGxpc3QuZmlsZXMocGF0aD0nZGF0YS9TRVEnLCBwYXR0ZXJuID0gJyouZmxhZ3N0YXRzJykKCiMgY3JlYXRlIHZlY3RvcnMgb2YgZmlsZXMgdG8gYmUgaW1wb3J0ZWQKbmFtZXMgPC0gc3Vic3RyKGZpbGVuYW1lcywgMSwgOSkKbGliIDwtIHN1YnN0cihmaWxlbmFtZXMsIDEsIDQpCgojIGltcG9ydCBkYXRhCmZvciAoaSBpbiBuYW1lcyl7CiAgZmlsZXBhdGggPC0gZmlsZS5wYXRoKCdkYXRhL1NFUScsIHBhc3RlKGksICdzdGF0cycsIHNlcCA9IiIpKQogIGFzc2lnbihpLCByZWFkLmNzdihmaWxlcGF0aCwgc2VwID0gIisiLCBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiTl9SZWFkcyIsICJDQVQiKSwKICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICAgICAgICAgICBzZWxlY3QoMToyKSkKfQoKIyBDcmVhdGUgbGlzdCBvZiBvbmUgZGF0YWZyYW1lIHBlciBmbGFnc3RhdHMgZmlsZSBhbmQgY3JlYXRlIHRpZHkgZGF0YSBzZXQKIyBzaG91bGQgYmUgMyBlbGVtZW50cy9saWJyYXJpZXMKcm0oZGZsaXN0X2ZsYWcpCgpkZmxpc3RfZmxhZyA8LSBsYXBwbHkobHMocGF0dGVybiA9ICIqZmxhZyIpLCBnZXQpCgojIENoYW5nZSBOX1JlYWRzIHRvIG51bWVyaWMKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPC0gZGZsaXN0X2ZsYWdbW2RmXV0KICB4W1snTl9SZWFkcyddXSA8LSBhcy5udW1lcmljKHhbWydOX1JlYWRzJ11dKQogIGRmbGlzdF9mbGFnW1tkZl1dIDwtIHgKfQoKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPC0gZGZsaXN0X2ZsYWdbW2RmXV0KICAKICBuIDwtIG5yb3coeCkvMTQKCiAgeCA8LSB4ICU+JQogICAgZmlsdGVyKGdyZXBsKCIwIG1hcHBlZHxwcm9wZXJseSBwYWlyZWR8bWFwUT49NSIsIENBVCkpICU+JQogICAgbXV0YXRlKE1BUFNUQVQgPSBpZmVsc2UoZ3JlcGwoIm1hcFE+PTUiLCBDQVQpLCAiTWlzbWF0Y2giLAogICAgICAgICAgICAgICAgICAgaWZlbHNlKGdyZXBsKCJwcm9wZXJseSIsIENBVCksICJQcm9wX1BhaXJlZCIsICJNYXBwZWQiKSkpICU+JQogICAgbXV0YXRlKEluZCA9IGMocmVwKDE6biwgZWFjaCA9IDMpKSkgJT4lIAogICAgIyBub3Qgc3VyZSBpZiBleHRyYSBpbmRpdmlkdWFsIGluIHRoZXJlIHNvbWVob3cKICAgIHNlbGVjdCg0LCAzLCAxKSAlPiUKICAgIHNwcmVhZChNQVBTVEFULCBOX1JlYWRzKQoKICBkZmxpc3RfZmxhZ1tbZGZdXSA8LSB4Cn0KCiMgQ3JlYXRlIG5ldyBkYXRhZnJhbWVzIHdpdGggc3VtbWFyeSBzdGF0cyBhbmQgYWRkIHRvIG1haW4gZmluYWwgZGF0YSBmcmFtZQpNYXBTdGF0cy5mbGFnIDwtIGRhdGEuZnJhbWUoKQoKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPSBzdW1tYXJpemUoZGZsaXN0X2ZsYWdbW2RmXV0sIFN1bV9NYXBwZWQgPSBzdW0oTWFwcGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWFkc19NYXBwZWQgPSBtZWFuKE1hcHBlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3VtX1BhaXJlZCA9IHN1bShQcm9wX1BhaXJlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVhbl9QYWlyZWQgPSBtZWFuKFByb3BfUGFpcmVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdW1fTWlzbWF0Y2ggPSBzdW0oTWlzbWF0Y2gpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1lYW5fTWlzbWF0Y2ggPSBtZWFuKE1pc21hdGNoKSkgJT4lCiAgbXV0YXRlKExpYiA9IGxpYltkZl0pICU+JQogIHNlbGVjdCg3LCAxOjYpCiAgTWFwU3RhdHMuZmxhZyA8LSBiaW5kX3Jvd3MoTWFwU3RhdHMuZmxhZywgeCkKfQoKIyB3cml0ZSB0byBmaWxlCndyaXRlLnRhYmxlKE1hcFN0YXRzLmZsYWcsICJyZXN1bHRzL01hcFN0YXRzLmZsYWciLCBxdW90ZSA9IEZBTFNFKQoKTWFwU3RhdHMuZmxhZwoKIyBjb21iaW5lIGZpbGVzCm1hcHN0YXRzIDwtIGxlZnRfam9pbihNYXBTdGF0cy5pZHgsIE1hcFN0YXRzLmZsYWcpICU+JQogIG11dGF0ZShQUk9QX01JU01BVENIID0gU3VtX01pc21hdGNoL1N1bV9NYXBwZWQpCgojIHdyaXRlIHN1bW1hcnkgc3RhdHMgZmlsZQp3cml0ZS50YWJsZShtYXBzdGF0cywgZmlsZSA9ICJyZXN1bHRzL0JXQV9tYXBwaW5nLnN0YXRzIiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIiAiKQoKYGBgCgojIyMgRXZhbHVhdGUgJiBjb21wYXJlIG1hcHBpbmcgcmVzdWx0cwoKQ29tcGFyZSBudW1iZXIgb2YgcmVmZXJlbmNlIGNvbnRpZ3MgZm9yIHdoaWNoIG5vIHJlYWRzIG1hcHBlZCB0byBwZXIgbGlicmFyeS4KCmBgYHtyIHBsb3QgbWFwc3RhdHMsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKbWFwc3RhdHMgPC0gcmVhZF9kZWxpbSgicmVzdWx0cy9CV0FfbWFwcGluZy5zdGF0cyIsIGRlbGltID0gIiAiKQoKIyBwbG90IG5vIG9mIGxvY2kgdnMgImVtcHR5IiBsb2NpCnAxIDwtIGdncGxvdChtYXBzdGF0cywgYWVzKHggPSBMaWIsIHkgPSBDT05USUdTX01BUFBFRCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMC4wNSkpICsKICBsYWJzKHggPSAibGlicmFyeSIsIHkgPSAiJSBjb250aWdzIHcvbm8gcmVhZHMgbWFwcGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBnZ3Bsb3QobWFwc3RhdHMsIGFlcyh4ID0gTGliLCB5ID0gUmVhZHNfTWFwcGVkKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBsYWJzKHggPSAibGlicmFyeSIsIHkgPSAibWVhbiByZWFkcyBtYXBwZWQgcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAzIDwtIGdncGxvdChtYXBzdGF0cywgYWVzKHggPSBMaWIsIHkgPSBQUk9QX01JU01BVENIKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBsYWJzKHggPSAiIix5ID0gIiUgcmVhZHMgbm90IG1hcHBlZCBhcyBwYWlyIikgKwogIHRoZW1lX3N0YW5kYXJkCgptdWx0aXBsb3QocDEsIHAyLCBwMywgY29scyA9IDMpCgpgYGAKCiMgU05QIGNhbGxpbmcKClRyYW5zZmVyIGNvcHkgb2YgYHJlZmVyZW5jZS5mYXN0YWAgYW5kIGFzc29jaWF0ZWQgZmlsZXMgaW50byBTTlAgY2FsbGluZyBkaXJlY3RvcnkuCgpDcmVhdGUgc3ltbGlua3MgZnJvbSBhbGwgYGZxYCwgYGJhbWAgYW5kIGBiYW0uYmFpYC1maWxlcyBmb3IgZWFjaCBzZXBhcmF0ZWx5IG1hcHBlZCBsaWJyYXJ5IGluIGBTTlBfQ2FsbGluZ2AgZm9sZGVyLgoKYGBge2Jhc2ggc29mdGxpbmsgZmlsZXMsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpsbiAtcyAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU0VRL0JNQS0xLyouZnEuZ3ogL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NOUF9DYWxsaW5nCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TRVEvQk1BLTEvKi5iYW0qIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TTlBfQ2FsbGluZwoKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NFUS9CTUEtMi8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TTlBfQ2FsbGluZwpsbiAtcyAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU0VRL0JNQS0yLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TRVEvQk1BLTMvKi5mcS5neiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NFUS9CTUEtMy8qLmJhbSogL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NOUF9DYWxsaW5nCgojIHJlbW92ZSB1bm5lY2Vzc2FyeSBmaWxlcwpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKcm0gY2F0LVJSRy5iYW0qCgpgYGAKCkV4ZWN1dGUgYGREb2NlbnRgIGZyb20gd2l0aGluIGBTTlBfQ2FsbGluZ2AtZm9sZGVyIHRvIGNhbGwgdmFyaWFudHMgYWNyb3NzIGFsbCBpbmRpdmlkdWFscyAoYWxsIGxpYnJhcmllcykuCgpgYGB7YmFzaCBjYWxsIFNOUHMsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKZERvY2VudAoKYGBgCgpGaWxlIGBUb3RhbHJhd1NOUHMudmNmYCBjb250YWlucyBhbGwgcmF3IFNOUC9JTkRFTCBjYWxscy4gRG8gbm90IG5lZWQgdG8ga2VlcCBsaW5rcyBvZiBgZnEuZ3pgLSwgYGJhbWAtLCBgLmJhbS5iYWlgLWZpbGVzIGFmdGVyIFNOUHMgaGF2ZSBiZWVuIGNhbGxlZC4gQ29weSBgVG90YWxSYVNOUHMudmNmYCB0byBgVkNGYCBmb3IgU05QIGZpbHRlcmluZy4KCmBgYHtiYXNoIGNvcHkgVG90YWxSYXdTTlBzIGZvciBmaWx0ZXJpbmcsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKcm0gKmZxLmd6ICpiYW0qCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcvVG90YWxSYXdTTlBzLnZjZiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvVkNGL3RlbXAvCgpgYGAKCiMgU05QIGZpbHRlcmluZwoKYGREb2NlbnRgIHVzZXMgYEZyZWVCYXllc2AgdG8gY2FsbCBTTlBzIGFuZCB3cml0ZSBhIFZDRi1maWxlIGBUb3RhbHJhd1NOUHMudmNmYC4gVGhpcyBkYXRhIHNldCB3YXMgZmlsdGVyZWQgdG8gcmVtb3ZlIGxvdyBxdWFsaXR5IGFuZCBhcnRlZmFjdHVhbCBTTlAgc2l0ZXMsIHBhcmFsb2dzIGFuZCBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyBiYXNlZCBvbiBsZXZlbHMgb2YgbWlzc2luZyBkYXRhLCBtaW5pbXVtL21heGltdW0gcmVhZCBkZXB0aCwgZ2Vub3R5cGUgY2FsbCByYXRlLCBhbmQgbWlub3IgYWxsZWxlIGZyZXF1ZW5jaWVzLiBDb250aWdzIG1heSBjb250YWluIG1vcmUgdGhhbiBvbmUgU05QOyB0aGUgc2NyaXB0IGByYWRfaGFwbG90eXBlci5wbGAgd2FzIHVzZWQgdG8gY3JlYXRlIGhhcGxvdHlwZXMgZm9yIGVhY2ggbG9jdXMuCgojIyBSYXcgZGF0YSAKCiMjIyBJbmRpdmlkdWFscy9Qb3B1bGF0aW9ucyBzYW1wbGVkCgpHZW5lcmF0ZSBhIGxpc3Qgb2YgYWxsIGluZGl2aWR1YWxzIGluY2x1ZGVkIGluIHRoZSBTTlAgZGF0YSBzZXQgY2FsbGVkIGJ5IEZyZWVCYXllcyBpbiB0aGUgZERvY2VudCBwaXBlbGluZS4KCmBgYHtiYXNoIHdyaXRlIHJhdyBpbmR2fQoKdmNmc2FtcGxlbmFtZXMgZGF0YS9WQ0YvdGVtcC9Ub3RhbFJhd1NOUHMudmNmID4gZGF0YS9WQ0YvcmF3LmluZAoKYGBgCgpVc2UgYEluZF9yYXdgIGZpbGUgdG8gd3JpdGUgdGV4dCBmaWxlcyBvZiBpbmRpdmlkdWFscyBpbiBlYWNoIGxpYnJhcnkgYW5kIGluIHJlZ2lvbmFsIGdyb3VwaW5ncy4gCgpgYGB7ciBjcmVhdGUgSW5kIGZpbGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBpbXBvcnQgaW5kaXZpZHVhbHMgaW4gcmF3IGRhdGEgc2V0IC0tLS0KSW5kX1JBVyA8LSByZWFkX2RlbGltKCJkYXRhL1ZDRi9yYXcuaW5kIiwgZGVsaW0gPSAiXHQiLCBjb2xfbmFtZXMgPSAiTElCX0lEIikgJT4lCiAgc2VwYXJhdGUoTElCX0lELCBpbnRvID0gYygiU1AiLCAiV0VMTCIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKQoKIyBjcmVhdGUgZmlsZXMgd2l0aCBpbmRpdmlkdWFscyBieSBwb3B1bGF0aW9uIC0tLS0KClNhbXBsZUluZm8gPC0gcmVhZF9kZWxpbSgiZGF0YS9QT1BHRU4vU2FtcGxlSW5mby50eHQiLCBkZWxpbSA9ICJcdCIpCgpJbmRfUkFXIDwtIGxlZnRfam9pbihJbmRfUkFXLCBTYW1wbGVJbmZvKQoKcG9wcyA8LSB1bmlxdWUoSW5kX1JBVyRQT1ApCgpmb3IgKHAgaW4gcG9wcyl7CiAgCiAgZGYgPC0gSW5kX1JBVyAlPiUKICAgIGZpbHRlcihQT1AgPT0gcCkgJT4lCiAgICBzZWxlY3QoTElCX0lEKQogIAogIHdyaXRlX2RlbGltKGRmLCBwYXN0ZSgiZGF0YS9WQ0YvIiwgcCwgIi5pbmQiLCBzZXAgPSAiIiksCiAgICAgICAgICAgIGRlbGltID0gIiIsIGNvbF9uYW1lcyA9IEZBTFNFKQogIAp9CgoKIyBjcmVhdGUgZmlsZXMgd2l0aCBpbmRpdmlkdWFscyBwZXIgbGlicmFyeSAtLS0tCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjFBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiMUIiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUExLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjJBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiMkIiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUEyLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjNBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiM0IiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUEzLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKIyMjIENvbXBhcmUgSW5kaXZpZHVhbCAmIFNOUCBzdGF0cwoKVXNlIGBWQ0Z0b29sc2AgdG8gY3JlYXRlIHN0YXRzIGZpbGVzIGZvciBkZXB0aCwgbWlzc2luZyBkYXRhLCBoZXRlcm96eWdvc2l0eSBhbmQgc2l0ZSBxdWFsaXR5IGZvciB0aGUgcmF3IGRhdGEuCgpgYGB7YmFzaCBxdWVyeSByYXcgc3RhdHN9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL1RvdGFsUmF3U05Qcy52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BX3JhdyAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tbWlzc2luZy1zaXRlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2luZ2xldG9ucwoKYGBgCgpDb21wYXJlIHJhdyBzdGF0cy4KICAgIApgYGB7ciBzdGF0cyByYXcsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19yYXcgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQV9yYXciKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX3JhdyA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQV9yYXciKQoKIyBwbG90IG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnAxIDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IE1JU1NfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgcmVhZCBkZXB0aCBwZXIgaW5kdiAtLS0tCnAyIDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gcmVhZCBkZXB0aCBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIG1pc3NpbmcgLS0tLQpwMyA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBNRUFOX0RFUFRIX0JNQV9yYXcsIHkgPSBNSVNTX0JNQV9yYXcpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUlTU19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgcGVyIGluZHYgLS0tLQpwNCA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBGaXNfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnA1IDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IEZpc19CTUFfcmF3LCB5ID0gTUlTU19CTUFfcmF3KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJGaXMgcGVyIGluZHYiLCB5ID0gIiUgbWlzc2luZyBkYXRhIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1lYW4gZGVwdGggcGVyIGluZHYgLS0tLQpwNiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBGaXNfQk1BX3JhdywgeSA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJGaXMgcGVyIGluZHYiLCB5ID0gIm1lYW4gZGVwdGggcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgLS0tLQpwNyA8LSBnZ3Bsb3QobG9jX3N0YXRzX3JhdywgYWVzKHggPSBNSVNTX0JNQV9yYXcpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuMSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDggPC0gZ2dwbG90KGxvY19zdGF0c19yYXcsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUFfcmF3KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BX3JhdywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19yYXcsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUFfcmF3LCB5ID0gTUlTU19CTUFfcmF3KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BX3JhdywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIFNOUCBxdWFsaXR5IC0tLS0Kc2l0ZV9xdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQV9yYXcubHF1YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoUFJPQiA9IDEwXigtUVVBTC8xMCkpCgp0ZW1wIDwtIGRhdGEuZnJhbWUobG9jX3N0YXRzX3JhdyRNRUFOX0RFUFRIX0JNQV9yYXcsIHNpdGVfcXVhbCRRVUFMKSAlPiUKICByZW5hbWUoZGVwdGggPSBsb2Nfc3RhdHNfcmF3Lk1FQU5fREVQVEhfQk1BX3JhdywgcXVhbCA9IHNpdGVfcXVhbC5RVUFMKQoKcDEwIDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oZGVwdGgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4ocXVhbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgbG9jdXMiLCB5ID0gIlNOUCBxdWFsaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnRlbXAgPC0gbG9jX3N0YXRzX3JhdyAlPiUKICBjb3VudChDSFIpCgpwMTEgPC0gbGVmdF9qb2luKHRlbXAsIGxvY19zdGF0c19yYXcpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyIsIHkgPSAibWVhbiBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEyIDwtIGxvY19zdGF0c19yYXcgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm1yYXcgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIGNvbHM9MikKCmBgYAoKIyMgQ2hvb3NlIHRocmVzaG9sZCB2YWx1ZXMgZm9yIHF1YWxpdHkgc2NvcmUsIGNvdmVyYWdlLCBtaXNzaW5nIGRhdGEsIG1pbm9yIGFsbGVsZXMgYW5kIG1hcHBpbmcvdmFyaWFudCBjYWxsaW5nIGFydGlmYWN0cwoKIyMjIEZpbHRlciAwOiBSZW1vdmUgTFEgaW5kaXZpZHVhbHMKClJlbW92ZSAoa25vd24pIGxvdyBxdWFsaXR5IGluZGl2aWR1YWxzIGZyb20gZGF0YSBzZXQ6CgpJZGVudGlmeSBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyB0byByZW1vdmUgZnJvbSB0aGUgZGF0YSBzZXQ7IGRlZmluZWQgYXMgaW5kaXZpZHVhbHMgd2l0aCBhIG1lYW4gY292ZXJhZ2Ugb2YgZml2ZSBvciBsZXNzIHJlYWRzIGFjcm9zcyBhbGwgbG9jaSwgd2l0aCBtb3JlIHRoYW4gMzElIG1pc3NpbmcgZGF0YSwgb3IgRmlzID4gKHRocmVzaG9sZHMgYmFzZWQgb24gZXhwbG9yYXRvcnkgZmlsdGVyaW5nKS4KCgpgYGB7ciBscSBpbmR2fQoKTFFpbmR2IDwtIGluZF9zdGF0c19yYXcgJT4lCiAgZmlsdGVyKE1FQU5fREVQVEhfQk1BX3JhdyA8PSA1IHwgTUlTU19CTUFfcmF3ID49IDAuMzEgfCBGaXNfQk1BX3JhdyA+IDAuMikgJT4lCiAgc2VsZWN0KElORFYpCgp3cml0ZV9kZWxpbShMUWluZHYsICJkYXRhL1ZDRi9MUV9yYXcuaW5kIiwgZGVsaW0gPSAiXHQiKQoKbnJvdyhMUWluZHYpCgpgYGAKClJlbW92ZSBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyBhbmQgZGVjb21wb3NlIGluZGVscy4KCmBgYHtiYXNoIGZpbHRlciBscSBpbmR2LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKIyBkZWNvbXBvc2UgaW5kZWxzCnZjZmFsbGVsaWNwcmltaXRpdmVzIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLWtlZXAtaW5mbyAtLWtlZXAtZ2VubyA+IGRhdGEvVkNGL3RlbXAvQk1BLnByaW0udmNmCgojIHJldGFpbiBvbmx5IFNOUHMgLyByZW1vdmUgTFEgaW5kaXZpZHVhbHMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucHJpbS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjAgLS1yZW1vdmUtaW5kZWxzIC0tcmVtb3ZlIGRhdGEvVkNGL0xRX3Jhdy5pbmQgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCiMgcXVlcnkgc3RhdHMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjAgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLXNpbmdsZXRvbnMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjAgLS1nZW5vLWRlcHRoCgpgYGAKCkNvbXBhcmUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMCwgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTEwLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9VFJVRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMCA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkYwIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKQoKbG9jX3N0YXRzX0YwIDwtIHJlYWQubG9jLnN0YXRzKGRpciA9ICJkYXRhL1ZDRi8iLCB2Y2YgPSAiQk1BLkYwIikKCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhpbmRfc3RhdHNfRjApYCBpbmRpdmlkdWFscyBhbmQgYHIgbnJvdyhsb2Nfc3RhdHNfRjApYCBsb2NpIGFmdGVyIHJlbW92aW5nIGxvdyBxdWFsaXR5IGluZGl2aWR1YWxzIGFuZCBkZWNvbXBvc2luZyBpbmRlbHMgc2V0IGludG8gU05Qcy4KCkltcG9ydCBzaW5nbGV0b25zIGFuZCBnZW5vdHlwZSBkZXB0aCBmaWxlIHRvIGNyZWF0ZSBsaXN0IG9mIGxvY2kgdG8gZXhjbHVkZSBiYXNlZCBvbiBkZXB0aC4KCmBgYHtyIHJlYWQgc2luZ2xldG9uIGdlbm90eXBlIGRlcHRoLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBudW1iZXIgb2YgaW5kaXZpZHVhbHMKbiA8LSBucm93KGluZF9zdGF0c19GMCkrMgoKIyByZWFkIHNpbmdsZXRvbnMgZmlsZQpzaW5nbGV0b25zIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjAuc2luZ2xldG9ucyIpICU+JQogIG11dGF0ZShWQVJJQU5UID0gaWZlbHNlKEFMTEVMRSAlaW4lIGMoIkEiLCAiVCIsICJDIiwgIkciKSwgIlNOUCIsICJJTkRFTCIpKQoKY2hyb20gPC0gdW5pcXVlKHNpbmdsZXRvbnMkQ0hST00pCgojIHJlYWQgZ2Vub3R5cGUgZGVwdGggZmlsZSBhbmQgam9pbiB3aXRoIHNpbmdsZXRvbnMKZ2RlcHRoIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjAuZ2RlcHRoIikgJT4lCiAgZmlsdGVyKENIUk9NICVpbiUgY2hyb20pICU+JQogIGdhdGhlcihrZXkgPSBJTkRWLCB2YWx1ZSA9IERFUFRILCAzOm4pCgpzaW5nbGV0b25zIDwtIGxlZnRfam9pbihzaW5nbGV0b25zLCBnZGVwdGgpCiAgCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYG5yb3coc2luZ2xldG9ucylgIHNpbmdsZXRvbnMuCgpgYGB7ciBkb3VibGV0b25zfQoKIyBmaWx0ZXIgZG91YmxldG9ucwpkb3VibGV0b25zIDwtIHNpbmdsZXRvbnMgJT4lCiAgZmlsdGVyKGBTSU5HTEVUT04vRE9VQkxFVE9OYCA9PSAiRCIpCgpgYGAKCk9mIHRob3NlIGBucm93KGRvdWJsZXRvbnMpYCBhcmUgY2FsbGVkIGFzIGEgaG9tb3p5Z290ZSBpbiBvbmUgaW5kaXZpZHVhbC4KCmBgYHtyIHNpbmdsZXRvbnMgcGVyIGNvbnRpZywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCiMgbnVtYmVyIG9mIGNvbnRpZ3MgaW4gZGF0YSBzZXQKY29udGlnc190b3RhbCA8LSBsb2Nfc3RhdHNfRjAgJT4lCiAgZGlzdGluY3QoQ0hSKQoKY29udGlnc19zaW5nbGV0b25zIDwtIHNpbmdsZXRvbnMgJT4lCiAgZGlzdGluY3QoQ0hST00pCgpjb250aWdzIDwtIHNpbmdsZXRvbnMgJT4lCiAgY291bnQoQ0hST00pCgpnZ3Bsb3QoY29udGlncywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2luZ2xldG9ucyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKVGhlIGRhdGEgc2V0IGNvbnRhaW5zIGBucm93KGNvbnRpZ3NfdG90YWwpYCBjb250aWdzLCBgbnJvdyhjb250aWdzX3NpbmdsZXRvbnMpYCAoYDJyb3VuZCggKG5yb3coY29udGlnc19zaW5nbGV0b25zKS9ucm93KGNvbnRpZ3NfdG90YWwpKjEwMCksIGRpZ2l0cyA9IDIpYCUpIGNvbnRhaW4gc2luZ2xldG9ucy4KCmBgYHtyIGRpc3RyaWJ1dGlvbiBzaW5ncGxldG9ucyBwZXIgY29udGlnLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD02fQoKY29udGlncyA8LSBzaW5nbGV0b25zICU+JQogIGdyb3VwX2J5KGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgJT4lCiAgY291bnQoQ0hST00pCgpnZ3Bsb3QoY29udGlncywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGZhY2V0X2dyaWQoLiB+IGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2YgZG91YmxldG9ucy9zaW5nZWx0b25zIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpUYXJnZXQgY292ZXJhZ2UgaXMgMjAgcmVhZHMgcGVyIGxvY3VzOyBmbGFnIHNpbmdsZXRvbnMgd2l0aCBkZXB0aCA8IDEwIHJlYWRzIGFuZCBkb3VibGV0b25zIHdpdGggZGVwdGggPCAyMCByZWFkcy4KCmBgYHtyfQoKc2luZ2xldG9ucyAlPiUgCiAgZ3JvdXBfYnkoYFNJTkdMRVRPTi9ET1VCTEVUT05gKSAlPiUKICBjb3VudChERVBUSCA8PSAxMCkKCmQgPC0gc2luZ2xldG9ucyAlPiUKICBmaWx0ZXIoYFNJTkdMRVRPTi9ET1VCTEVUT05gID09ICJEIiAmIERFUFRIIDw9IDIwKSAKICAKTFEgPC0gc2luZ2xldG9ucyAlPiUKICBmaWx0ZXIoREVQVEggPD0gMTApICU+JQogIGJpbmRfcm93cyhkKSAlPiUKICBzZWxlY3QoQ0hST00sIFBPUykKCndyaXRlX2RlbGltKExRLCAiZGF0YS9WQ0YvTFFfRjAubG9jaSIsIGRlbGltID0gIlx0IiwgY29sX25hbWVzID0gRkFMU0UpCgpgYGAKCkRpc3RyaXVidGlvbiBvZiBnZW5vdHlwZSBkZXB0aCBwZXIgc2luZ2xldG9uL2RvdWJsZXRvbi4KCmBgYHtyIGRpc3RyaWJ1dGlvbiBnZW5vIGRlcHRoIHBlciBzaW5nbGV0b24sIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTZ9CgpnZ3Bsb3Qoc2luZ2xldG9ucywgYWVzKHggPSBERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBmYWNldF9ncmlkKC4gfiBgU0lOR0xFVE9OL0RPVUJMRVRPTmAsIHNjYWxlcyA9ICJmcmVlIikgKwogIGxhYnMoeCA9ICJyZWFkIGRlcHRoIikgKwogIHNjYWxlX3lfc3FydCgpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpRdWFudGlsZXMgZGlzdHJpYnV0aW9uIG9mIHJlYWQgZGVwdGggZm9yIFNOUCBsb2NpIGNhbGxlZCBpbiBvbmx5IG9uZSBpbmRpdmlkdWFsLgoKYGBge3IgcXVhbnRpbGUgc2luZ2xldG9uIGRlcHRofQoKcXVhbnRpbGUoc2luZ2xldG9ucyRERVBUSCwgcHJvYnMgPSBjKC4wNSwgLjI1LCAuNSwgLjc1LCAuOTUsIC45OSkpCgpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBkb3VibGV0b25zIChob216eWdvdXMgZ2Vub3R5cGUgZm9yIHRoYXQgaW5kaXZpZHVhbCkgYW5kIHNpbmdsZXRvbnMgKGhldGVyb3p5Z290ZSBnZW5vdHlwZSkuCgpgYGB7ciBkaXN0cmlidXRpb24gbm8gc2luZ2xldG9ucyBwZXIgaW5kdiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCkluZCA8LSBzaW5nbGV0b25zICU+JQogIGdyb3VwX2J5KGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgJT4lCiAgY291bnQoSU5EVikKCkluZCA8LSBsZWZ0X2pvaW4oSW5kLCBpbmRfc3RhdHNfRjApCgpnZ3Bsb3QoSW5kLCBhZXMoeCA9IG4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1MCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGZhY2V0X2dyaWQoLiB+IGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2luZ2xldG9ucyBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpRdWFudGlsZXMgZGlzdHJpYnV0aW9uIG51bWJlciBvZiBzaW5nbGV0b25zIGNhbGxlZCBpbiBvbmUgaW5kaXZpZHVhbC4KCmBgYHtyIHF1YW50aWxlIHNpbmdsZXRvbnMgcGVyIGluZHZ9CgpxdWFudGlsZShJbmQkbiwgcHJvYnMgPSBjKC4wMSwgLjA1LCAuMjUsIC41LCAuNzUsIC45OSkpCgpgYGAKCkNvbXBhcmUgdGhlIG51bWJlciBvZiBTTlBzIHZzIGNvbXBsZXggdmFyaWFudHMgKElOREVMcykuCgpgYGB7ciBzaW5nbGV0b24gdmFyaWFudCB0eXBlfQoKY291bnQoc2luZ2xldG9ucywgVkFSSUFOVCkKCmBgYAoKIyMjIEZpbHRlciAxOiBDb25maWRlbmNlIGluIFNOUCBjYWxsCiAgICAKVGhlIFFVQUwgY29sdW1uIG9mIGEgVkNGIGZpbGUgaXMgYSBwaHJlZCBiYXNlZCBzY29yZSBpbmRpY2F0aW5nIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSB2YXJpYW50IHNob3duIGluIHRoZSBBTFQgY29sdW1uIGlzIHdyb25nLiBHaXZlbiB0aGUgUGhyZWQgcXVhbGl0eSBzY29yZSAoUSksIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIGJhc2UgaXMgaW5jb3JyZWN0bHkgY2FsbGVkIChQKSwgUSA9IC0xMChMb2cxMFApLiBBIHF1YWxpdHkgc2NvcmUgb2YgMjAgaW5kaWNhdGVzLCBhIDEgaW4gMTAwIGNoYW5jZSB0aGF0IHRoZSBTTlAgc2l0ZSBoYXMgYmVlbiBjYWxsZWQgaW5jb3JyZWN0bHkgKGkuZS4gOTklIHByb2JhYmlsaXR5IHRoYXQgY29ycmVjdCBjYWxsKS4KCkZpbHRlciBsb2NpIHdpdGggcXVhbGl0eSBzY29yZSA8IDIwIGFuZCBzaW5nbGV0b25zL2RvdWJsZXRvbnMgd2l0aCBsb3cgcmVhZCBkZXB0aCAoPDEwLzIwIHJlYWRzKS4gQ29kZSBnZW5vdHlwZXMgd2l0aCBnZW5vdHlwZSBjYWxsIHF1YWxpdHkgPCAyMCBvciAgZ2Vub3R5cGUgZGVwdGggPCA1IGFzIG1pc3NpbmcuCgpgYGB7YmFzaCBmaWx0ZXIgTFEgU05QIGNhbGxzfQoKIyBmaWx0ZXIgTFEgU05QIGNhbGxzCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYwLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjEgLS1taW5RIDIwIC0tbWluR1EgMjAgLS1taW5EUCA1IC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvTFFfRjAubG9jaSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKIyBxdWVyeSBzdGF0cwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMSAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tbWlzc2luZy1zaXRlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tZ2Vuby1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMSAtLXNpbmdsZXRvbnMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEgLS1pbmR2LWZyZXEtYnVyZGVuCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tZnJlcSAKCmBgYAoKQ29tcGFyZSBzdGF0cyBwb3N0LWZpbHRlcmluZy4KCmBgYHtyIHN0YXRzIEYxLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGxvYWQgc3RhdHMgZmlsZXMgLS0tLQppbmRfc3RhdHNfRjEgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMSIpICU+JQogIHNlcGFyYXRlKElORFYsIGludG8gPSBjKCJTUCIsICJMSUIiLCAiU0FNUExFX0lEIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UpCgpsb2Nfc3RhdHNfRjEgPC0gcmVhZC5sb2Muc3RhdHMoZGlyID0gImRhdGEvVkNGLyIsIHZjZiA9ICJCTUEuRjEiKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGluZF9zdGF0c19GMSlgIGluZGl2aWR1YWxzIGFuZCBgciBucm93KGxvY19zdGF0c19GMSlgIFNOUCBzaXRlcy4KClJlbW92aW5nIGxvdyBjb25maWRlbmNlIFNOUCBsb2NpIGFuZCBnZW5vdHlwZSBjYWxscyByZXN1bHRzIGluIGEgcmVkdWN0aW9uIGluIHRoZSBudW1iZXIgb2YgdGhlIChtYXhpbXVtKSBTTlBzIHBlciBsb2N1cy4KCmBgYHtyIE4gU05QcywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnAxIDwtIGxvY19zdGF0c19yYXcgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBsb2Nfc3RhdHNfRjEgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMWEgPC0gbXVsdGlwbG90KHAxLCBwMiwgY29scz0xKQoKYGBgCgpDb2RpbmcgZ2Vub3R5cGVzIHdpdGggbG93IHJlYWQgZGVwdGggKDwgNSkgYXMgbWlzc2luZywgcmVzdWx0cyBpbiBhbiBvdmVyYWxsIGluY3JlYXNlIGluIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgYW5kIGEgc2hpZnQgaW4gbW9yZSBpbmRpdmlkdWFscyB3aXRoIG1vcmUgbWlzc2luZyBkYXRhIC0gdGhpcyBpcyBiZWNhdXNlIGluZGl2aWR1YWxzIChhbmQgbG9jaSkgd2l0aCBjb3ZlcmFnZSBpc3N1ZXMgYXJlIG5vdyBjaGFyYWN0ZXJpemVkIGJ5IGhpZ2hlciBtaXNzaW5nIGRhdGEuCgpgYGB7ciBtaXNzaW5nIGRhdGEgRjEsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgppcmF3IDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQV9yYXcuaW1pc3MiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIEZfTUlTUykgJT4lCiAgcmVuYW1lKHJhdyA9IEZfTUlTUykKCmltaXNzIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5pbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoSU5EViwgRl9NSVNTKSAlPiUKICByZW5hbWUoRjEgPSBGX01JU1MpCgppbWlzcyA8LSBsZWZ0X2pvaW4oaW1pc3MsIGlyYXcpCgpwMSA8LSBnZ3Bsb3QoaW1pc3MsIGFlcyh4ID0gcmF3LCB5ID0gRjEpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArCiAgbGFicyh4ID0gImluZHYgbWlzc2luZyBkYXRhIHJhdyIsIHkgPSAiaW5kdiBtaXNzaW5nIGRhdGEgRjEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmxyYXcgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BX3Jhdy5sbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgcmVuYW1lKHJhdyA9IEZfTUlTUykKCmxtaXNzIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5sbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgcmVuYW1lKEYxID0gRl9NSVNTKQoKbG1pc3MgPC0gbGVmdF9qb2luKGxtaXNzLCBscmF3KQoKcDIgPC0gZ2dwbG90KGxtaXNzLCBhZXMoeCA9IHJhdywgeSA9IEYxKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIGxhYnMoeCA9ICJsb2NpIG1pc3NpbmcgZGF0YSByYXciLCB5ID0gImxvY2kgbWlzc2luZyBkYXRhIEYxIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMWIgPC0gbXVsdGlwbG90KHAxLCBwMiwgY29scz0yKQoKYGBgCgpDb21wYXJlIGRlcHRoIGluZGl2aWR1YWxzIGFmdGVyIHJlbW92aW5nIExRIFNOUCBsb2NpIGFuZCBnZW5vdHlwZXMuCgpgYGB7ciBkZXB0aCBGMSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmlyYXcgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BX3Jhdy5pZGVwdGgiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIE1FQU5fREVQVEgpICU+JQogIHJlbmFtZShyYXcgPSBNRUFOX0RFUFRIKQoKaWRlcHRoIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5pZGVwdGgiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIE1FQU5fREVQVEgpICU+JQogIHJlbmFtZShGMSA9IE1FQU5fREVQVEgpCgppZGVwdGggPC0gbGVmdF9qb2luKGlyYXcsIGlkZXB0aCkKCmdncGxvdChpZGVwdGgsIGFlcyh4ID0gcmF3LCB5ID0gRjEpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwKSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIGluZCByYXciLCB5ID0gIm1lYW4gZGVwdGggaW5kIEYxIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCiMjIyBGaWx0ZXIgMjogR2Vub3R5cGUgY2FsbCByYXRlIGFuZCBhbGxvd2VkIG1pc3NpbmcgZGF0YSBwZXIgaW5kdgoKUmVtb3ZlIGxvY2kgd2l0aCBnZW5vdHlwZSBjYWxsIHJhdGUgPCA1MCUgYW5kIG1pbmltdW0gbWVhbiBkZXB0aCA8IDE1IHJlYWRzIGFjcm9zcyBhbGwgaW5kaXZpZHVhbHMuCgpgYGB7YmFzaCAyYSBnZW5vIDwgNTB9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYyYSAtLW1heC1taXNzaW5nIDAuNSAtLW1pbi1tZWFuRFAgMTUgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCiMgbGlicmFyeSBCTUEtMQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQTEgLS1rZWVwIGRhdGEvVkNGL0JNQTEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BMSAtLW1pc3Npbmctc2l0ZQoKIyBsaWJyYXJ5IEJNQS0yCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BMiAtLWtlZXAgZGF0YS9WQ0YvQk1BMi5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEyIC0tbWlzc2luZy1zaXRlCgojIGxpYnJhcnkgQk1BLTMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEzIC0ta2VlcCBkYXRhL1ZDRi9CTUEzLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQTMgLS1taXNzaW5nLXNpdGUKCiMgQ2FtcGVjaGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9DQU1QIC0ta2VlcCBkYXRhL1ZDRi9DQU1QLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0FNUC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0NBTVAgLS1taXNzaW5nLXNpdGUKCiMgQ2hhbmRlbGV1ciBTb3VuZAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0NTIC0ta2VlcCBkYXRhL1ZDRi9DUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0NTLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQ1MgLS1taXNzaW5nLXNpdGUKCiMgQ29ycHVzIENocmlzdGkgQmF5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQ0MgLS1rZWVwIGRhdGEvVkNGL0NDLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9DQyAtLW1pc3Npbmctc2l0ZQoKIyBGbG9yaWRhIEF0bGFudGljCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxBIC0ta2VlcCBkYXRhL1ZDRi9GTEEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEEgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIFNvdXRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxHUyAtLWtlZXAgZGF0YS9WQ0YvRkxHUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0ZMR1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEdTIC0tbWlzc2luZy1zaXRlCgojIEZsb3JpZGEgR3VsZiBOb3J0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMR04gLS1rZWVwIGRhdGEvVkNGL0ZMR04uaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEdOLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvRkxHTiAtLW1pc3Npbmctc2l0ZQoKIyBMb3Vpc2lhbmEKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9MQSAtLWtlZXAgZGF0YS9WQ0YvTEEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9MQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0xBIC0tbWlzc2luZy1zaXRlCgojIE1pc3Npc3NpcHBpIFNvdW5kCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvTUlTUyAtLWtlZXAgZGF0YS9WQ0YvTUlTUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL01JU1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9NSVNTIC0tbWlzc2luZy1zaXRlCgojIE1vYmlsZSBCYXkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9NQiAtLWtlZXAgZGF0YS9WQ0YvTUIuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NQi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL01CIC0tbWlzc2luZy1zaXRlCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgcGVyIGxpYnJhcnkuCgpgYGB7ciBsbWlzcyBwZXIgbGliLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBjcmVhdGUgZW1wdHkgbGlzdApsb2NfbWlzc2luZyA8LSBsaXN0KCkKCmZvciAoaSBpbiAxOjMpIHsKICAKICBsaWIgPC0gcGFzdGUoIkJNQSIsIGksIHNlcCA9ICIiKQogIAogIGxvY19taXNzaW5nW1tpXV0gPC0gcmVhZF9kZWxpbShwYXN0ZSgiZGF0YS9WQ0YvIiwgbGliLCAiLmxtaXNzIiwgc2VwID0gIiIpLCBkZWxpbSA9ICJcdCIpICU+JQogICAgc2VsZWN0KENIUiwgUE9TLCBGX01JU1MpICU+JQogICAgbXV0YXRlKExJQiA9IGxpYikKICAKfQoKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIGFsbCBpbmZvcm1hdGlvbgpsb2NfbWlzc2luZyA8LSBsZHBseShsb2NfbWlzc2luZywgZGF0YS5mcmFtZSkKCmdncGxvdChsb2NfbWlzc2luZywgYWVzKHggPSBGX01JU1MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBsb2N1cyIpICsKICBmYWNldF9ncmlkKExJQiB+IC4pICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGbGFnIGxvY2kgdGhhdCB3ZXJlIG5vdCBjYWxsZWQgaW4gPiA1MCUgb2YgaW5kaXZpZHVhbHMgaW4gYSBnaXZlbiBsaWJyYXJ5LgoKYGBge3J9CgojIGlkZW50aWZ5IGxvY2kgd2l0aCBoaWdoIG1pc3NpbmcgZGF0YSBpbiBlYWNoIGxpYnJhcnkKU05QcyA8LSBmaWx0ZXIobG9jX21pc3NpbmcsIEZfTUlTUyA+IDAuNSkgJT4lCiAgYXJyYW5nZShDSFIsIFBPUykKCmNvdW50KFNOUHMsIExJQikKCkxRbG9jaV9saWIgPC0gU05QcyAlPiUKICBzZWxlY3QoQ0hSLCBQT1MpICU+JQogIHVuaXF1ZSgpCgpgYGAKCkEgdG90YWwgb2YgYHIgTFFsb2NpX2xpYmAgbG9jaSB3ZXJlIGNhbGxlZCBpbiBsZXNzIHRoYW4gNTAlIG9mIGluZGl2aWR1YWxzIGluIG9uZSBvciBtb3JlIGxpYnJhcmllcy4gTG9jaSBiZWluZyBpbmNvbnNpc3RlbnRseSBjYWxsZWQgYmV0d2VlbiBsaWJyYXJpZXMgY2FuIHJlc3VsdCBpbiBsaWJyYXJ5IGVmZmVjdHMuCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIHBlciBzYW1wbGUgbG9jYXRpb24uCgpgYGB7ciBsbWlzcyBwZXIgbG9jLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgY3JlYXRlIGVtcHR5IGxpc3QKbG9jX21pc3NpbmcgPC0gbGlzdCgpCgojIHBvcHMgdG8gbG9vcCBvdmVyCnBvcCA8LSB1bmlxdWUoSW5kX1JBVyRQT1ApCgojIGltcG9ydCBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzCmZvciAocCBpbiBwb3ApIHsKICAKICBsb2NfbWlzc2luZ1tbcF1dIDwtIHJlYWRfZGVsaW0ocGFzdGUoImRhdGEvVkNGLyIsIHAsICIubG1pc3MiLCBzZXAgPSAiIiksIGRlbGltID0gIlx0IikgJT4lCiAgICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgICBtdXRhdGUoUE9QID0gcCkKICAKfQoKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIGFsbCBpbmZvcm1hdGlvbgpsb2NfbWlzc2luZyA8LSBsZHBseShsb2NfbWlzc2luZywgZGF0YS5mcmFtZSkgJT4lCiAgc2VsZWN0KC1gLmlkYCkKCmdncGxvdChsb2NfbWlzc2luZywgYWVzKHggPSBGX01JU1MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIGZhY2V0X2dyaWQoUE9QIH4gLikgKwogIHNjYWxlX3lfc3FydCgpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGbGFnIGxvY2kgdGhhdCB3ZXJlIG5vdCBjYWxsZWQgaW4gPiA3NSUgb2YgaW5kaXZpZHVhbHMgYXQgYSBnaXZlbiBzYW1wbGUgbG9jYXRpb24uCgpgYGB7cn0KCiMgaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggbGlicmFyeQpTTlBzIDwtIGZpbHRlcihsb2NfbWlzc2luZywgRl9NSVNTID4gMC4yNSkgJT4lCiAgYXJyYW5nZShDSFIsIFBPUykKCmNvdW50KFNOUHMsIFBPUCkKCkxRbG9jaV9wb3AgPC0gU05QcyAlPiUKICBzZWxlY3QoQ0hSLCBQT1MpICU+JQogIHVuaXF1ZSgpCgpMUWxvY2kgPC0gYmluZF9yb3dzKExRbG9jaV9saWIsIExRbG9jaV9wb3ApICU+JQogIHVuaXF1ZSgpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byBmaWxlCndyaXRlLnRhYmxlKExRbG9jaSwgZmlsZSA9ICJkYXRhL1ZDRi9MUV9GMmIubG9jaSIsIAogICAgICAgICAgICBjb2wubmFtZXM9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKUmVtb3ZlIGxvY2kgdGhhdCB3ZXJlIG5vdCBjb25zaXN0ZW50bHkgY2FsbGVkIGFjcm9zcyBhbGwgbGlicmFyaWVzIGFuZCBzYW1wbGUgbG9jYXRpb25zLgoKYGBge2Jhc2ggZmlsdGVyIG1pc3NpbmcgYnkgbGlifQoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjJiIC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvTFFfRjJiLmxvY2kgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMmIgLS1taXNzaW5nLWluZHYKCmBgYAoKSWRlbnRpZnkgaW5kaXZpZHVhbHMgd2l0aCA+IDI1JSBtaXNzaW5nIGRhdGEKCmBgYHtyIGltaXNzID4gNTAsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTR9CgojIGRldGVybWluZSBjdXRvZmYKaW1pc3MgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLkYyYi5pbWlzcyIsIAogICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgCgpnZ3Bsb3QoaW1pc3MsIGFlcyh4ID0gRl9NSVNTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgppbWlzcyA8LSBpbWlzcyAlPiUKICBmaWx0ZXIoRl9NSVNTID4gMC4yNSkgJT4lCiAgc2VsZWN0KElORFYpCgp3cml0ZS50YWJsZShpbWlzcywgImRhdGEvVkNGL0YyYl9MUS5pbmR2IiwKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBmbGFnZ2VkIGluZGl2aWR1YWxzLgoKYGBge2Jhc2ggZmlsdGVyIExRIGluZHZ9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GMiAtLXJlbW92ZSBkYXRhL1ZDRi9GMmJfTFEuaW5kdiAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjIgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLWdlbm8tZGVwdGgKCmBgYAoKQW5hbHl6ZSBzdGF0cyBwb3N0LWZpbHRlcmluZzoKCmBgYHtyIHN0YXRzIEYyLCBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGxvYWQgc3RhdHMgZmlsZXMgLS0tLQppbmRfc3RhdHNfRjIgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMiIpICU+JQogIHNlcGFyYXRlKElORFYsIGludG8gPSBjKCJTUCIsICJMSUIiLCAiU0FNUExFX0lEIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UpCgpsb2Nfc3RhdHNfRjIgPC0gcmVhZC5sb2Muc3RhdHMoZGlyID0gImRhdGEvVkNGLyIsIHZjZiA9ICJCTUEuRjIiKQoKYGBgCgoKIyMjIEZpbHRlciAzOiBGaWx0ZXIgbG9jaSBhbmQgaW5kaXZpZHVhbHMgYmFzZWQgb24gZGVwdGgsIHZhcmlhbmNlIGluIGRlcHRoIGFuZCBnZW5vdHlwZSBjYWxsIHJhdGUKCkRldGVybWluZSBtZWFuIGRlcHRoIGFuZCB2YXJpYW5jZSBwZXIgbG9jdXMgcGVyIGxpYnJhcnkuCgpgYGB7YmFzaCBkZXB0aCBkYXRhIHBlciBsaWJ9CgojIGxpYnJhcnkgQk1BLTEKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQTEgLS1rZWVwIGRhdGEvVkNGL0JNQTEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BMSAtLXNpdGUtbWVhbi1kZXB0aAoKIyBsaWJyYXJ5IEJNQS0yCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEyIC0ta2VlcCBkYXRhL1ZDRi9CTUEyLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQTIgLS1zaXRlLW1lYW4tZGVwdGgKCiMgbGlicmFyeSBCTUEtMwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BMyAtLWtlZXAgZGF0YS9WQ0YvQk1BMy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEzIC0tc2l0ZS1tZWFuLWRlcHRoCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIGRlcHRoIGNvdmVyYWdlIHBlciBsb2N1cyBwZXIgbGlicmFyeS4gSWRlbnRpZnkgbG9jaSB0aGF0IGRvIG5vdCBoYXZlIGNvbnNpc3RlbnQgY292ZXJhZ2UgYmV0d2VlbiBsaWJyYXJpZXMgKGNhbiBsZWFkIHRvIGxpYnJhcnkgZWZmZWN0cyksIGFuZC9vciBhY3Jvc3MgaW5kaXZpZHVhbHMuIAoKYGBge3IgZGVwdGggcGVyIGxvY3VzIHBlciBsaWIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNyZWF0ZSBlbXB0eSBsaXN0CmxvY19kZXB0aCA8LSBsaXN0KCkKCiMgaW1wb3J0IGRlcHRoIGRhdGEgcGVyIGxvY3VzCmxvY19kZXB0aFtbMV1dIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQTEubGRlcHRoLm1lYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoTElCID0gIkJNQTEiKQoKbG9jX2RlcHRoW1syXV0gPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BMi5sZGVwdGgubWVhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIG11dGF0ZShMSUIgPSAiQk1BMiIpCgpsb2NfZGVwdGhbWzNdXSA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi9CTUEzLmxkZXB0aC5tZWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgbXV0YXRlKExJQiA9ICJCTUEzIikKCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCBhbGwgaW5mb3JtYXRpb24KbG9jX2RlcHRoIDwtIGxkcGx5KGxvY19kZXB0aCwgZGF0YS5mcmFtZSkKCmdncGxvdChsb2NfZGVwdGgsIGFlcyh4ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRILCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIpICsKICBmYWNldF9ncmlkKExJQiB+IC4pICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpJZGVudGlmeSBsb2NpIHdpdGggbGFyZ2UgdmFyaWFuY2UgaW4gbWVhbiBkZXB0aCBhY3Jvc3MgbGlicmFyaWVzIGFuZC9vciBpbmRpdmlkdWFscyBieSBjYWxjdWxhdGluZyB0aGUgY29lZmZpY2llbnQgb2YgdmFyaWFuY2UgKFNURC9NRUFOKS4KCmBgYHtyIGNhbGN1bGF0ZSB2YXJpYXRpb24gaW4gZGVwdGgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNhbGN1bGF0ZSBtZWFuIGRlcHRoIHdlaWdodGVkIGJ5IGxpYnJhcnkKZGVwdGhfY29tcCA8LSBsb2NfZGVwdGggJT4lCiAgZ3JvdXBfYnkoTElCKSAlPiUKICBkaXN0aW5jdChDSFJPTSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lCiAgc2VsZWN0KC1QT1MpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShDSFJPTSkgJT4lCiAgc3VtbWFyaXNlKE1FQU4gPSBtZWFuKE1FQU5fREVQVEgpLAogICAgICAgICAgICBTVEQgPSBzZChNRUFOX0RFUFRIKSkKCiMgbWVhbiBkZXB0aCBhY3Jvc3MgYWxsIGluZGl2aWR1YWxzCnRlbXAgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLkYyLmxkZXB0aC5tZWFuIiwgCiAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIGRpc3RpbmN0KENIUk9NLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUKICBzZWxlY3QoLVBPUykgJT4lCiAgbXV0YXRlKFNURF9ERVBUSCA9IHNxcnQoVkFSX0RFUFRIKSkKCiMgY2FsY3VsYXRlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbgpkZXB0aF9jb21wIDwtIGxlZnRfam9pbihkZXB0aF9jb21wLCB0ZW1wKSAlPiUKICBtdXRhdGUoQ09FRkZfVkFSX0xJQiA9IFNURC9NRUFOKjEwMCwKICAgICAgICAgQ09FRkZfVkFSX0lORCA9IFNURF9ERVBUSC9NRUFOX0RFUFRIKjEwMCkKCmBgYAoKQ29tcGFyZSBtZWFuIGFjcm9zcyBhbGwgaW5kaXZpZHVhbCB0byBtZWFuIHdlaWdodGVkIGJ5IGxpYnJhcnkgYW5kIGNvZWZmaWNpZW50IG9mIHZhcmlhbmNlIG9mIHJlYWQgZGVwdGggYWNyb3NzIGluZGl2aWR1YWxzIGFuZCBiZXR3ZWVuIGxpYnJhcmllczoKCmBgYHtyIG1lYW4gc3RkIGRlcHRoLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD04LjV9CgpwMSA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBNRUFOX0RFUFRILCB5ID0gTUVBTikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAibWVhbiB3ZWlnaHRlZCBieSBsaWIiKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDIgPC0gZ2dwbG90KGRlcHRoX2NvbXAsIGFlcyh4ID0gQ09FRkZfVkFSX0lORCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoQ09FRkZfVkFSX0lORCwgLjk5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJjb2VmZiB2YXIgZGVwdGggYWNyb3NzIGFsbCBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBDT0VGRl9WQVJfSU5ELCB5ID0gQ09FRkZfVkFSX0xJQikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgbGFicyh4ID0gImNvZWZmIHZhciBkZXB0aCBhY3Jvc3MgYWxsIGluZHYiLCB5ID0gImNvZWZmIHZhciBtZWFuIGRlcHRoIGJldHcgbGliIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBDT0VGRl9WQVJfTElCKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBxdWFudGlsZShDT0VGRl9WQVJfTElCLCAuOTkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gImNvZWZmIHZhciBkZXB0aCBiZXR3ZWVuIGxpYiIpICsKICB0aGVtZV9zdGFuZGFyZAoKbTNhIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgY29scz0yKQoKYGBgCgpJZiBsb2NpIGhhdmUgY29uc2lzdGVudCBjb3ZlcmFnZSBhY3Jvc3MgbG9jaSB0aGUgbWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyBhY3Jvc3MgYWxsIGluZGl2aWR1YWxzIGFuZCB3ZWlnaHRlZCBieSBsaWJyYXJ5IHNob3VsZCBmYWxsIG9uIHRoZSByZWQgZGlhZ29uYWwuIAoKRmxhZyBsb2NpIHRoYXQgaGF2ZSBoaWdoIHZhcmlhdGlvbiBpbiBtZWFuIGNvdmVyYWdlIGJldHdlZW4gaW5kaXZpZHVhbHMgYW5kIGJldHdlZW4gbGlicmFyaWVzLgoKYGBge3IgTFEgbG9jaSB2YXJpYXRpb24gY292ZXJhZ2V9CgojIGlkZW50aWZ5IGxvY2kgaGlnaCB2YXJpYXRpb24gaW4gY292ZXJhZ2UKY29udGlnc192YXIgPC0gZGVwdGhfY29tcCAlPiUKICBmaWx0ZXIoQ09FRkZfVkFSX0xJQiA+IDkwIHwgQ09FRkZfVkFSX0lORCA+IDE1MCkKClNOUHNfdmFyIDwtIGZpbHRlcihsb2NfZGVwdGgsIENIUk9NICVpbiUgY29udGlnc192YXIkQ0hST00pICU+JQogIGRpc3RpbmN0KENIUk9NLCBQT1MpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byB0ZXh0IGZpbGUsIHVzZSBmaWxlIHdpdGggdmNmdG9vbHMgdG8gcmVtb3ZlIHBvc2l0aW9ucyBmcm9tIGRhdGFzZXQgCndyaXRlLnRhYmxlKFNOUHNfdmFyLCBmaWxlID0gImRhdGEvVkNGL0xRX0YzLmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBsb2NpIGZsYWdnZWQgZm9yIGhpZ2ggdmFyaWFuY2UgaW4gZGVwdGggYWNyb3NzIGFsbCBpbmRpdmlkdWFscyBhbmQgYmV0d2VlbiBsaWJyYXJpZXMgKHJlbW92ZXMgbGlicmFyeSBlZmZlY3RzKSwgZmlsdGVyIGxvY2kgd2l0aCBtZWFuIGRlcHRoIDwgMjAgYW5kIGdlbm90eXBlIGNhbGwgcmF0ZSA8IDc1JQoKYGBge2Jhc2ggZmlsdGVyIHZhcmlhbmNlIGluIGNvdmVyYWdlIGxvY2l9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYzYSAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL0xRX0YzLmxvY2kgLS1taW4tbWVhbkRQIDE1IC0tbWF4LW1pc3NpbmcgMC43NSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjNhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYzYSAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GM2EgLS1nZW5vLWRlcHRoCgpgYGAKCkNvbXBhcmUgbWVhbiBkZXB0aCBhbmQgbnVtYmVyIG9mIHNpdGVzIGNhbGxlZCBwZXIgaW5kaXZpZHVhbC4KCmBgYHtyIGlkZXB0aCBzaXRlcyB2cyBkZXB0aCBJLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYzYS5pZGVwdGgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBOX1NJVEVTLCB5ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEuNSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDAuNzUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZGFya2JsdWUiLCBzaXplID0gMC43NSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2l0ZXMiLCB5ID0gIm1lYW4gcmVhZCBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpVc2UgZ2Vub3R5cGUgZGVwdGggZmlsZSB0byBpZGVudGlmeSBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggdmFyaWFuY2UgaW4gcmVhZCBkZXB0aCBhY3Jvc3MgbG9jaS4KCmBgYHtyIHZhcmlhbmNlIGRlcHRoIGluZGl2aWR1YWwgSX0KCiMgbnVtYmVyIG9mIGluZGl2aWR1YWxzCm4gPC0gbnJvdyhpbmRfc3RhdHNfRjIpKzEKCiMgcmVhZCBnZW5vdHlwZSBkZXB0aCAmIGNvZGUgdmFsdWVzIDwgNSBhcyBtaXNzaW5nCmdkZXB0aCA8LSByZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYzYS5nZGVwdGgiKSAlPiUKICBzZWxlY3QoLVBPUykgJT4lCiAgZGlzdGluY3QoQ0hST00sIC5rZWVwX2FsbCA9IFRSVUUpICU+JQogIGdhdGhlcihrZXkgPSBJTkRWLCB2YWx1ZSA9IERFUFRILCAzOm4pICU+JQogIG11dGF0ZShERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigtMSwgMCwgREVQVEgpKSwKICAgICAgICAgREVQVEggPSBhcy5udW1lcmljKGdzdWIoIlxcPDFcXD4iLCAwLCBERVBUSCkpLAogICAgICAgICBERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigiXFw8MlxcPiIsIDAsIERFUFRIKSksCiAgICAgICAgIERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwzXFw+IiwgMCwgREVQVEgpKSwKICAgICAgICAgREVQVEggPSBhcy5udW1lcmljKGdzdWIoIlxcPDRcXD4iLCAwLCBERVBUSCkpKQoKIyBjYWxjdWxhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCmlkZXB0aCA8LSBnZGVwdGggJT4lCiAgZ3JvdXBfYnkoSU5EVikgJT4lCiAgc3VtbWFyaXplKFRPVEFMID0gc3VtKERFUFRIKSwKICAgICAgICAgICAgTUFYID0gbWF4KERFUFRIKSwKICAgICAgICAgICAgTUVBTl9OT04wID0gbWVhbihERVBUSFtERVBUSCA+IDBdKSwKICAgICAgICAgICAgTUVBTiA9IG1lYW4oREVQVEgpLAogICAgICAgICAgICBNRURJQU4gPSBtZWRpYW4oREVQVEgpLAogICAgICAgICAgICBWQVIgPSB2YXIoREVQVEgpLAogICAgICAgICAgICBTVEQgPSBzZChERVBUSCkpICU+JQogIG11dGF0ZShDT0VGRl9WQVIgPSBTVEQvTUVBTiwKICAgICAgICAgUkFUSU9fTUVBTl9NRURJQU4gPSBNRUFOL01FRElBTikKCmlkZXB0aCA8LSBsZWZ0X2pvaW4oaWRlcHRoLCBpbmRfc3RhdHNfRjIpCgpgYGAKCkNvbXBhcmUgdmFyaWFiaWxpdHkgb2YgZGVwdGggd2l0aGluIGluZGl2aWR1YWxzLgoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMH0KCnAxIDwtIGdncGxvdChpZGVwdGgsIGFlcyh4ID0gTUFYLCB5ID0gVE9UQUwpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImF1dG8iLGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChpZGVwdGgsIGFlcyh4ID0gVE9UQUwsIHkgPSBWQVIpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImF1dG8iLGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAzIDwtIGdncGxvdChpZGVwdGgsIGFlcyhNQVgsIE1FRElBTikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiYXV0byIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDQgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBNRUFOLCB5ID0gTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNSA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IENPRUZGX1ZBUiwgeSA9IFJBVElPX01FQU5fTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNiA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoTUVBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDE1LCBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNyA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoTUVESUFOKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTAsIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA4IDwtIGdncGxvdChpZGVwdGgsIGFlcyhSQVRJT19NRUFOX01FRElBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA5IDwtIGdncGxvdChpZGVwdGgsIGFlcyhDT0VGRl9WQVIpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAyNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAxMCA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IENPRUZGX1ZBUiwgeSA9IE1JU1NfQk1BLkYyKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4yNSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZGFya3JlZCIsIHNpemUgPSAwLjc1KSArCiAgdGhlbWVfc3RhbmRhcmQKCgptM2IgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgY29scz0yKQoKYGBgCgpGbGFnIExRIGluZGl2aWR1YWxzLgoKYGBge3J9CgpMUV9kZXB0aCA8LSBpZGVwdGggJT4lCiBmaWx0ZXIoTUVBTiA8PSAxMCB8IE1FRElBTiA8PSA1KSAlPiUKIHNlbGVjdChJTkRWKQoKTFFfZGVwdGgKIAp3cml0ZS50YWJsZShMUV9kZXB0aCwgImRhdGEvVkNGL0YzX0xRLmluZHYiLAogICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgpSZW1vdmUgZmxhZ2dlZCBsb2NpIGFuZCBpbmRpdmlkdWFscy4KCmBgYHtiYXNoIGZpbHRlciB2YXJpYW5jZSBpbiBjb3ZlcmFnZX0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYzIC0tcmVtb3ZlIGRhdGEvVkNGL0YzX0xRLmluZHYgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYzIC0tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1zaXRlLW1lYW4tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1taXNzaW5nLXNpdGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1oZXQKCmBgYAoKQ29tcGFyZSBzdGF0cyBwb3N0LWZpbHRlcmluZzoKCmBgYHtyIHN0YXRzIEYzLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMyA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkYzIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSkKCmxvY19zdGF0c19GMyA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GMyIpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19GMywgYWVzKHggPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1pc3NpbmcgZGF0YSBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjMsIHkgPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWlzc2luZyBkYXRhIHBlciBsb2N1cyAtLS0tCnA0IDwtIGdncGxvdChsb2Nfc3RhdHNfRjMsIGFlcyh4ID0gTUlTU19CTUEuRjMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDUgPC0gZ2dwbG90KGxvY19zdGF0c19GMywgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gcmVhZCBkZXB0aCBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCByZWFkIGRlcHRoIHZzIG1pc3NpbmcgZGF0YSAtLS0tCnA2IDwtIGdncGxvdChsb2Nfc3RhdHNfRjMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjMsIHkgPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm0zIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBjb2xzPTIpCgpgYGAKCiMjIyBGaWx0ZXIgNDogQWxsZWxlIGJhbGFuY2UKCkFCOiBBbGxlbGUgYmFsYW5jZSBhdCBoZXRlcm96eWdvdXMgc2l0ZXM6IGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIHJhdGlvIG9mIHJlYWRzIHNob3dpbmcgdGhlIHJlZmVyZW5jZSBhbGxlbGUgdG8gYWxsIHJlYWRzLCBjb25zaWRlcmluZyBvbmx5IHJlYWRzIGZyb20gaW5kaXZpZHVhbHMgY2FsbGVkIGFzIGhldGVyb3p5Z291cwoKYGBge2Jhc2ggcXVlcnkgSU5GTyBzdGF0cyBJLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY3V0IC1mOCBCTUEuRjMucmVjb2RlLnZjZiB8IGdyZXAgLW9lICJBQj1bWzpkaWdpdDpdXS5bWzpkaWdpdDpdXVtbOmRpZ2l0Ol1dW1s6ZGlnaXQ6XV0iIHwgc2VkIC1zICdzL0FCPS8vZycgPiBCTUEuRjQuQUIKCmBgYAoKQWxsZWxlIGJhbGFuY2UgaXMgdGhlIHJhdGlvIG9mIHJlYWRzIGZvciByZWZlcmVuY2UgYWxsZWxlIHRvIGFsbCByZWFkcywgY29uc2lkZXJpbmcgb25seSByZWFkcyBmcm9tIGluZGl2aWR1YWxzIGNhbGxlZCBhcyBoZXRlcm96eWdvdXMuIFZhbHVlcyByYW5nZSBmcm9tIDAgLSAxOyBhbGxlbGUgYmFsYW5jZSAoZm9yIHJlYWwgbG9jaSkgc2hvdWxkIGJlIGFwcHJveC4gMC41LiBGaWx0ZXIgU05QcyBmb3Igd2hpY2ggdGhlIHdpdGggYWxsZWxlIGJhbGFuY2UgPCAwLjI1IGFuZCA+IDAuNzUuCgpgYGB7ciBwbG90IEFCLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01fQoKcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjQuQUIiLAogICAgICAgICAgIGNvbC5uYW1lcyA9ICJBQiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQUIpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjUsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNzUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGaWx0ZXIgY29udGlncyB3aXRoIFNOUCBjYWxscyB3aXRoIEFCID4gMC4yNSwgQUIgPiAwLjc1OyByZXRhaW4gbG9jaSB2ZXJ5IGNsb3NlIHRvIDAgKHJldGFpbiBsb2NpIHRoYXQgYXJlIGZpeGVkIHZhcmlhbnRzKS4gUmVtb3ZlIGdlbm90eXBlcyBpZiB0aGUgcXVhbGl0eSBzdW0gb2YgdGhlIHJlZmVyZW5jZSBvciBhbHRlcm5hdGUgYWxsZWxlIHdhcyAwLgoKYGBge2Jhc2gsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgojIHRoaXMgd29ya3MuLi4gbm90IHN1cmUgd2h5IGNhbnQgd3JpdGUgdG8gZmlsZSBpbiB0aGUgZm9sZGVyCnZjZmZpbHRlciAtcyAtZiAiQUIgPiAwLjI1ICYgQUIgPCAwLjc1IHwgQUIgPCAwLjAxIHwgQUIgPiAwLjk5IiAtcyAtZyAiUVIgPiAwIHwgUUEgPiAwIiBCTUEuRjMucmVjb2RlLnZjZiA+IEJNQS5GNC52Y2YgCm1hd2sgJyEvIy8nIEJNQS5GNC52Y2YgfCB3YyAtbAoKYGBgCgpSZW1haW5pbmcgU05QczogNTIsNjEwLgoKCiMjIyBGaWx0ZXIgNTogcXVhbGl0eS9kZXB0aCByYXRpbwoKYGBge2Jhc2h9CgojIHNpdGUgZGVwdGgKY3V0IC1mOCBCTUEuRjQudmNmIHwgZ3JlcCAtb2UgIkRQPVswLTldKiIgfCBzZWQgLXMgJ3MvRFA9Ly9nJyA+IEJNQS40LkRFUFRICgojIHF1YWxpdHkgc2NvcmUKbWF3ayAnIS8jLycgIEJNQS5GNC52Y2YgfCBjdXQgLWYxLDIsNiA+IEJNQS5GNC5sb2NpLnF1YWwKCmBgYAoKQ29tcGFyZSBxdWFsaXR5L2RlcHRoIHJhdGlvLgoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgZGVwdGgKZGVwdGggPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuNC5ERVBUSCIsCiAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gImRlcHRoIikKCiMgcXVhbGl0eSBzY29yZQpxdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL3RlbXAvQk1BLkY0LmxvY2kucXVhbCIsCiAgICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJsb2N1cyIsICJwb3MiLCAicXVhbCIpKQoKdGVtcCA8LSBiaW5kX2NvbHMocXVhbCwgZGVwdGgpICU+JQogIG11dGF0ZShyYXRpbyA9IHF1YWwvZGVwdGgpCgpnZ3Bsb3QodGVtcCwgYWVzKHggPSByYXRpbykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMjUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5ODUiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yLCBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpSZW1vdmUgbG9jaSB3aXRoIHF1YWxpdHkvZGVwdGggcmF0aW8gPCAwLjIKCmBgYHtiYXNofQoKdmNmZmlsdGVyIC1zIC1mICJRVUFMIC8gRFAgPiAwLjIiIEJNQS5GNC52Y2YgPiBCTUEuRjUudmNmIAoKbWF3ayAnIS8jLycgQk1BLkY1LnZjZiB8IHdjIC1sCgpgYGAKClJlbWFpbmluZyBTTlBzOiAzMSw4ODAuCgojIyMgRmlsdGVyIDY6IG1hcHBpbmcgcXVhbGl0eQoKYGBge2Jhc2ggcXVlcnkgbWFwcGluZyBxdWFsaXR5LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY3V0IC1mOCBCTUEuRjUudmNmIHwgZ3JlcCAtb2UgIk1RTT1bMC05XSoiIHwgc2VkIC1zICdzL01RTT0vL2cnID4gQk1BLkY1Lk1RTQoKY3V0IC1mOCBCTUEuRjUudmNmIHwgZ3JlcCAtb2UgIk1RTVI9WzAtOV0qIiB8IHNlZCAtcyAncy9NUU1SPS8vZycgPiBCTUEuRjUuTVFNUgoKYGBgCgpSZW1vdmUgbG9jaSBiYXNlZCBvbiByYXRpbyBvZiBtYXBwaW5nIHF1YWxpdHkgZm9yIHJlZmVyZW5jZSBhbmQgYWx0ZXJuYXRlIGFsbGVsZSwgaS5lLiBzaXRlcyB0aGF0IGhhdmUgYSBoaWdoIGRpc2NyZXBhbmN5IGJldHdlZW4gdGhlIG1hcHBpbmcgcXVhbGl0aWVzIG9mIHR3byBhbGxlbGVzLgoKYGBge3IgcGxvdCBtYXAgcXVhbCByYXRpb3MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9Cgp0ZW1wIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL3RlbXAvQk1BLkY1Lk1RTSIsIGNvbC5uYW1lcyA9ICJNUU0iKQoKbWFwcXVhbCA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNS5NUU1SIiwgY29sLm5hbWVzID0gIk1RTVIiKQoKbWFwcXVhbCA8LSBiaW5kX2NvbHMobWFwcXVhbCwgdGVtcCkgJT4lCiAgbXV0YXRlKHJhdGlvID0gTVFNL01RTVIpCgpmaWx0ZXIgPC0gbWFwcXVhbCAlPiUKICBmaWx0ZXIocmF0aW8gPCAwLjI1IHwgcmF0aW8gPiAxLjc1KQoKZ2dwbG90KG1hcHF1YWwsIGFlcyh4ID0gTVFNLCB5ID0gTVFNUikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEpICsgCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBzaXplID0gMSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gNCwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMC41NzEsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIsIGFlcyh4ID0gTVFNLCB5ID0gTVFNUiksIHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJyZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjUpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjUpKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKRmlsdGVyIGxvY2kgd2l0aCBtYXBwaW5nIHF1YWxpdHkgcmF0aW8gPCAwLjI1IGFuZCA+IDEuNzUuCgpgYGB7YmFzaCBmaWx0ZXIgbWFwIHF1YWwgcmF0aW99Cgp2Y2ZmaWx0ZXIgLXMgLWYgIk1RTSAvIE1RTVIgPiAwLjI1ICYgTVFNIC8gTVFNUiA8IDEuNzUiIEJNQS5GNS52Y2YgPiBCTUEuRjYudmNmCgptYXdrICchLyMvJyBCTUEuRjYudmNmIHwgd2MgLWwKCmBgYAoKUmVtYWluaW5nIFNOUHM6IDMwLDE4My4KCiMjIyBGaWx0ZXIgNzogU3RyYW5kIGJhbGFuY2UKClNSRjogTnVtYmVyIG9mIHJlZmVyZW5jZSBvYnNlcnZhdGlvbnMgb24gdGhlIGZvcndhcmQgc3RyYW5kClNBRjogTnVtYmVyIG9mIGFsdGVybmF0ZSBvYnNlcnZhdGlvbnMgb24gdGhlIGZvcndhcmQgc3RyYW5kClNSUjogTnVtYmVyIG9mIHJlZmVyZW5jZSBvYnNlcnZhdGlvbnMgb24gdGhlIHJldmVyc2Ugc3RyYW5kClNBUjogTnVtYmVyIG9mIGFsdGVybmF0ZSBvYnNlcnZhdGlvbnMgb24gdGhlIHJldmVyc2Ugc3RyYW5kCgpgYGB7YmFzaCBxdWVyeSBzdHJhbmRlZG5lc3MsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU0FGPVswLTldKiIgfCBzZWQgLXMgJ3MvU0FGPS8vZycgPiBCTUEuRjYuU0FGCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU0FSPVswLTldKiIgfCBzZWQgLXMgJ3MvU0FSPS8vZycgPiBCTUEuRjYuU0FSCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU1JGPVswLTldKiIgfCBzZWQgLXMgJ3MvU1JGPS8vZycgPiBCTUEuRjYuU1JGCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU1JSPVswLTldKiIgfCBzZWQgLXMgJ3MvU1JSPS8vZycgPiBCTUEuRjYuU1JSCgpgYGAKClBhaXJlZCBlbmQgcmVhZHMgc2hvdWxkIG5vdCBvdmVybGFwLCBhbmQgYSBTTlAgc2l0ZSBzaG91bGQgb25seSBiZSBjb3ZlcmVkIGJ5IGVpdGhlciB0aGUgZm9yd2FyZCBvciByZXZlcnNlIHJlYWQgKHN0cmFuZCkuIAoKYGBge3IgcGxvdCBzdHJhbmRlZG5lc3MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9CgpTQUYgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjYuU0FGIiwKICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gIlNBRiIpCgpTQVIgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjYuU0FSIiwKICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gIlNBUiIpCgpzdHJhbmRzIDwtIGJpbmRfY29scyhTQUYsIFNBUikKClNSRiA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNi5TUkYiLAogICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSAiU1JGIikKCnN0cmFuZHMgPC0gYmluZF9jb2xzKHN0cmFuZHMsIFNSRikKClNSUiA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNi5TUlIiLAogICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSAiU1JSIikKCnN0cmFuZHMgPC0gYmluZF9jb2xzKHN0cmFuZHMsIFNSUikgJT4lCiAgbXV0YXRlKHJhdGlvQSA9IFNBRi9TQVIsIHJhdGlvUiA9IFNSRi9TUlIpCgpnZ3Bsb3Qoc3RyYW5kcywgYWVzKHggPSBTQUYsIHkgPSBTQVIpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDAuMSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMTAwLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKUmVtb3ZlIFNOUCBzaXRlcyB0aGF0IGhhdmUgPiAxMDB4IG1vcmUgZm9yd2FyZCBhbHRlcm5hdGUgcmVhZHMgdGhhbiByZXZlcnNlIGFsdGVybmF0ZSByZWFkcyBhbmQgPiAxMDB4IG1vcmUgZm9yd2FyZCByZXZlcnNlIHJlYWRzIHRoYW4gcmV2ZXJzZSBhbHRlcm5hdGUgcmVhZHMuCgpgYGB7YmFzaCBmaWx0ZXIgc3RyYW5kZWRuZXNzfQoKdmNmZmlsdGVyIC1mICJTQUYgLyBTQVIgPiAxMDAgJiBTUkYgLyBTUlIgPiAxMDAgfCBTQVIgLyBTQUYgPiAxMDAgJiBTUlIgLyBTUkYgPiAxMDAiIC1zIEJNQS5GNi52Y2YgPiBCTUEuRjcudmNmCgptYXdrICchLyMvJyBCTUEuRjcudmNmIHwgd2MgLWwKCmBgYAoKTnVtYmVyIG9mIFNOUHMgcmVtYWluaW5nOiAyNiw3MjIuCgojIyMgRmlsdGVyIDg6IFByb3Blcmx5IHBhaXJlZCBzdGF0dXMKClBBSVJFRDogUHJvcG9ydGlvbiBvZiBvYnNlcnZlZCBhbHRlcm5hdGUgYWxsZWxlcyB3aGljaCBhcmUgc3VwcG9ydGVkIGJ5IHByb3Blcmx5IHBhaXJlZCByZWFkIGZyYWdtZW50cwpQQUlSRURSOiBQcm9wb3J0aW9uIG9mIG9ic2VydmVkIHJlZmVyZW5jZSBhbGxlbGVzIHdoaWNoIGFyZSBzdXBwb3J0ZWQgYnkgcHJvcGVybHkgcGFpcmVkIHJlYWQgZnJhZ21lbnRzCgpJZGVudGlmeSBsb2NpIHdpdGggb25seSB1bnBhaXJlZCByZWFkcyBtYXBwaW5nIHRvIHRoZW0gLSBhbiBhcnRpZmFjdCBpbnRyb2R1Y2VkIGR1ZSBkZSBub3ZvIHJlZmVyZW5jZSBhc3NlbWJseS4gQ29tcGFyZSBudW1iZXIgb2YgcGFpcmVkIHJlYWRzIG1hcHBpbmcgdGhlIHJlZmVyZW5jZSBhbmQgdGhlIGFsdGVybmF0ZSBhbGxlbGVzIHRvIGlkZW50aWZ5IGRpc2NyZXBhbmN5IGluIHRoZSBwYWlyZWQgc3RhdHVzIGZvciByZWFkcyBzdXBwb3J0aW5nIHJlZmVyZW5jZSBhbmQgYWx0ZXJuYXRlIGFsbGVsZXMuCgpgYGB7YmFzaCBmaWx0ZXIgcGFpcmVkIHN0YXR1cywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCnZjZmZpbHRlciAtZiAiUEFJUkVEID4gMC4wNSAmIFBBSVJFRFIgPiAwLjA1ICYgUEFJUkVEUiAvIFBBSVJFRCA8IDEuNzUgJiBQQUlSRURSIC8gUEFJUkVEID4gMC4yNSB8IFBBSVJFRCA8IDAuMDUgJiBQQUlSRURSIDwgMC4wNSIgLXMgQk1BLkY3LnZjZiA+IEJNQS5GOC52Y2YKCm1hd2sgJyEvIy8nIEJNQS5GOC52Y2YgfCB3YyAtbAoKYGBgCgpOdW1iZXIgb2YgU05QcyBpbiBkYXRhIHNldDogMjMsNzc4LgoKIyMjIEZpbHRlciA5OiBNYXhpbXVtIGRlcHRoICYgUXVhbGl0eQoKSWRlbnRpZnkgZGlzdHJpYnV0aW9uIG9mIGRlcHRoIChiYXNlZCBvbiBvcmlnaW5hbCBkYXRhIHNldCkgdG8gaWRlbnRpZnkgbG9jaSB3aXRoIGV4Y2VzcyBjb3ZlcmFnZS4KCk9yaWdpbmFsIG51bWJlciBvZiBpbmRpdmlkdWFscyBpbiBkYXRhIHNldCBpcyBgciBucm93KGluZF9zdGF0c19yYXcpYCAoSU5GTyBmbGFncyBpbiBmaWx0ZXJlZCBkYXRhIHNldCBhcmUgYXJlIGJhc2VkIG9uIG9yaWdpbmFsIG51bWJlciBvZiBpbmRpdmlkdWFscyBpbiBkYXRhIHNldCkuCgpDcmVhdGUgZmlsZSB3aXRoIHRoZSBvcmlnaW5hbCBzaXRlIGRlcHRoIGFuZCBxdWFsaXR5IHNjb3JlIGZvciBlYWNoIHNpdGU6CgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgc2l0ZSBkZXB0aApjdXQgLWY4IEJNQS5GOC52Y2YgfCBncmVwIC1vZSAiRFA9WzAtOV0qIiB8IHNlZCAtcyAncy9EUD0vL2cnID4gQk1BLkY4LkRFUFRICgojIHF1YWxpdHkgc2NvcmUKbWF3ayAnIS8jLycgIEJNQS5GOC52Y2YgfCBjdXQgLWYxLDIsNiA+IEJNQS5GOC5sb2NpLnF1YWwKCmBgYAoKQ2FsY3VsYXRlIGF2ZXJhZ2UgZGVwdGggYW5kIHN0YW5kYXJkIGRldmlhdGlvbjoKCmBgYHtyIHBsb3QgZGVwdGggdnMgcXVhbCwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NX0KCiMgZGVwdGgKZGVwdGggPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjguREVQVEgiLAogICAgICAgICAgICAgICAgICAgIGNvbC5uYW1lcyA9ICJkZXB0aCIpCgojIHF1YWxpdHkgc2NvcmUKcXVhbCA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GOC5sb2NpLnF1YWwiLAogICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygibG9jdXMiLCAicG9zIiwgInF1YWwiKSkKCiMgbWVhbiBkZXB0aAptZWFuX2RlcHRoIDwtIG1lYW4oZGVwdGgkZGVwdGgpCgojIHN0YW5kYXJkIGRldmlhdGlvbgpzdGQgPC0gc2QoZGVwdGgkZGVwdGgpCgojIGNhbGN1bGF0ZSBjdXRvZmYKY3V0b2ZmIDwtIHN1bShtZWFuX2RlcHRoICsgKDIqc3RkKSkKCiMgaWRlbnRpZnkgU05QcyB3aXRoIGV4Y2VzcyAoaS5lLiBkZXB0aCA+IG1lYW4gZGVwdGggKyAxIHN0YW5kYXJkIGRldmlhdGlvbgojIGFuZCBxdWFsaXR5IHNjb3JlIDwgMnggdGhlIGRlcHRoIGF0IHRoYXQgc2l0ZQpkZiA8LSBiaW5kX2NvbHMocXVhbCwgZGVwdGgpICU+JQogIG11dGF0ZShxdWFsY3V0b2ZmID0gMipkZXB0aCkKCnJlbW92ZWxvYyA8LSBkZiAlPiUKICBmaWx0ZXIoZGVwdGggPiBjdXRvZmYpICU+JQogIGZpbHRlcihxdWFsIDwgMipkZXB0aCkKCiMgcGxvdApnZ3Bsb3QoZGYsIGFlcyh4ID0gZGVwdGgsIHkgPSBxdWFsKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcmVtb3ZlbG9jLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCksIHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJyZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBkZiwgYWVzKHggPSBkZXB0aCwgeSA9IHF1YWxjdXRvZmYpLCBjb2xvciA9ICJibHVlIiwgIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY3V0b2ZmLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKTFEgPC0gcmVtb3ZlbG9jICU+JQogIHNlbGVjdChsb2N1cywgcG9zKQoKd3JpdGUudGFibGUoTFEsICJkYXRhL1ZDRi90ZW1wL0xRX0Y5LmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgpNZWFuIGRlcHRoIHBlciBsb2N1cyAoYWNyb3NzIGFsbCBpbmRpdnVhbHMpIGlzIGByIG1lYW5fZGVwdGhgIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIGByIHN0ZGAuIAoKRmlsdGVyIFNOUCBzaXRlIHdpdGggZGVwdGggPiBtZWFuIGRlcHRoICsgMSBzdGFuZGFyZCBkZXZpYXRpb24gPSBgciBzdW0obWVhbl9kZXB0aCArIDIqc3RkKWAgYW5kIHRoYXQgaGF2ZSBxdWFsaXR5IHNjb3JlcyA8IDJ4IHRoZSBkZXB0aCBhdCB0aGF0IHNpdGUgYW5kIG91dHB1dCBkZXB0aCBwZXIgc2l0ZS4KCmBgYHtiYXNoIGZpbHRlciBkZXB0aCBxdWFsLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKdmNmdG9vbHMgLS12Y2YgIGRhdGEvVkNGL3RlbXAvQk1BLkY4LnZjZiAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL3RlbXAvTFFfRjkubG9jaSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbCAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GOWEKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkY5YS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOWEgLS1zaXRlLW1lYW4tZGVwdGgKCmBgYAoKQ29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIG1lYW4gZGVwdGggcGVyIHNpdGUgYXZlcmFnZWQgYWNyb3NzIGluZGl2aWR1YWxzIHRvIGRldGVybWluZSBjdXQtb2ZmIHZhbHVlIG9mIHNpdGVzIHdpdGggZXhjZXNzaXZlbHkgaGlnaCBkZXB0aCBpbmRpY2F0aXZlIG9mIHBhcmFsb2dzL211bHRpY29weSBsb2NpLgoKYGBge3IgcGxvdCBkZXB0aCBkaXN0LCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBjYWxjdWxhdGUgbWVhbiBkZXB0aCBwZXIgc2l0ZSAoMTc3IGluZGl2aWR1YWxzKQpyZWFkLnRhYmxlKCJkYXRhL1ZDRi9CTUEuRjlhLmxkZXB0aC5tZWFuIiwKICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBNRUFOX0RFUFRIKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IHF1YW50aWxlKE1FQU5fREVQVEgsIC45NSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoTUVBTl9ERVBUSCwgLjk5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3lfc3FydCgpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgc2l0ZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDaG9vc2UgY3V0LW9mZiBmb3IgbWF4aW11bSBtZWFuIHJlYWQgZGVwdGggPSAzMDAuCgpgYGB7YmFzaCBmaWx0ZXIgbWF4IGRlcHRofQoKdmNmdG9vbHMgLS12Y2YgIGRhdGEvVkNGL3RlbXAvQk1BLkY4LnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GOSAtLW1heC1tZWFuRFAgMzAwIC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvdGVtcC9MUV9GOS5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsIAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjkucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjkgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLWhldAoKYGBgCgpEZXB0aCBkaXN0cmlidXRpb24gcGVyIGxvY3VzIGFmdGVyIGZpbHRlcmluZzoKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkY5LmxkZXB0aC5tZWFuIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpBbmFseXplIHN0YXRzIHBvc3QtZmlsdGVyaW5nOgoKYGBge3Igc3RhdHMgRjksIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GOSA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkY5IikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSkKCmxvY19zdGF0c19GOSA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GOSIpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19GOSwgYWVzKHggPSBNSVNTX0JNQS5GOSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjksIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1pc3NpbmcgZGF0YSBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0Y5LCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkY5KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjksIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjksIHkgPSBNSVNTX0JNQS5GOSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GOSwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWlzc2luZyBkYXRhIHBlciBsb2N1cyAtLS0tCnA0IDwtIGdncGxvdChsb2Nfc3RhdHNfRjksIGFlcyh4ID0gTUlTU19CTUEuRjkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GOSwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDUgPC0gZ2dwbG90KGxvY19zdGF0c19GOSwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GOSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDYgPC0gZ2dwbG90KGxvY19zdGF0c19GOSwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GOSwgeSA9IE1JU1NfQk1BLkY5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuRjksIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKbTMgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIGNvbHM9MikKCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhsb2Nfc3RhdHNfRjkpYCBTTlAgc2l0ZXMgYW5kIGByIG5yb3coaW5kX3N0YXRzX0Y5KWAgaW5kaXZpZHVhbHMuCgoKIyMjIEZpbHRlciAxMDogTWlzc2luZyBkYXRhIGFuZCBtaW5pbXVtIGRlcHRoIHBlciBsb2N1cwoKRmlsdGVyIGxvY2kgd2l0aCBtZWFuIHJlYWQgZGVwdGggPCAxNSBhbmQgZ2Vub3R5cGUgY2FsbCByYXRlIDwgOTAlLgoKYGBge2Jhc2ggZ2VubyA5MCBtZWFuRFAgMTV9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMCAtLW1pbi1tZWFuRFAgMTUgLS1tYXgtbWlzc2luZyAwLjkgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEwIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEwLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEwIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1oYXJkeQoKYGBgCgojIyMgRmlsdGVyIDExOiBFeGNlc3MgaGV0ZXJvenlnb3NpdHkKCklkZW50aWZ5IFNOUHMgd2l0aCBtb3JlIHRoYW4gMC41IGhldGVyb3p5Z29zaXR5IGFuZCBzaWduaWZpY2FudC4KCmBgYHtyfQoKIyBjYWxjdWxhdGUgb2JzZXJ2ZWQgaGV0ZXJvenlnb3NpdHkKaHdlIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMTAuaHdlIiwgCiAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSkgJT4lCiAgc2VsZWN0KC1DaGlTcV9IV0UpICU+JQogIHNlcGFyYXRlKGBPQlMuSE9NMS5IRVQuSE9NMi5gLCAKICAgICAgICAgICBpbnRvID0gYygib2JzX2hvbTEiLCAib2JzX2hldCIsICJvYnNfaG9tMiIpLCAKICAgICAgICAgICBzZXAgPSAiLyIsIGNvbnZlcnQgPSBUUlVFKSAlPiUKICBzZXBhcmF0ZShgRS5IT00xLkhFVC5IT00yLmAsIAogICAgICAgICAgIGludG8gPSBjKCJleHBfaG9tMSIsICJleHBfaGV0IiwgImV4cF9ob20yIiksIAogICAgICAgICAgIHNlcCA9ICIvIiwgY29udmVydCA9IFRSVUUpICU+JSAgIAogIG11dGF0ZShIbyA9IG9ic19oZXQvKG9ic19ob20xICsgb2JzX2hvbTIgKyBvYnNfaGV0KSwKICAgICAgICAgSGUgPSBleHBfaGV0LyhleHBfaG9tMSArIGV4cF9ob20yICsgZXhwX2hldCkpICU+JQogIHNlbGVjdChDSFIsIFBPUywgb2JzX2hvbTEsIGV4cF9ob20xLCBvYnNfaG9tMiwgZXhwX2hvbTIsIFBfSEVUX0RFRklDSVQsIG9ic19oZXQsIGV4cF9oZXQsIFBfSEVUX0VYQ0VTUywgSG8sIEhlLCBQX0hXRSkKCmBgYAoKRGlzdHJpYnV0aW9uIG9mIG9ic2VydmVkIGhldGVyb3p5Z29zaXR5LgoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCmdncGxvdChod2UsIGFlcyh4ID0gSG8pKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC41LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm9ic2VydmVkIGhldGVyb3p5Z29zaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCklkZW50aWZ5IGxvY2kgd2l0aCBoZXRlcm96eWdvc2l0eSA+IDAuNSwgdGhlbiBjb3JyZWN0IHAtdmFsdWVzIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyB1c2luZyBCZW5qYW1pbmktSG9jaGJlcmcgbWV0aG9kLgoKYGBge3J9CgojIGlkZW50aWZ5IGNvbnRpZ3Mgd2l0aCBTTlBzIHdpdGggSG8gPiAwLjUgJiBzaWduaWZpY2FudApleGNlc3NfaHdlIDwtIGh3ZSAlPiUKICBmaWx0ZXIoSG8gPiAwLjUpICU+JQogIG11dGF0ZShwX2FkaiA9IHAuYWRqdXN0KFBfSEVUX0VYQ0VTUyksIG1ldGhvZCA9ICJmZHIiKSAlPiUKICBmaWx0ZXIocF9hZGogPCAwLjAxKQoKY29udGlncyA8LSBod2UgJT4lCiAgZmlsdGVyKENIUiAlaW4lIGV4Y2Vzc19od2UkQ0hSKSAlPiUKICBzZWxlY3QoQ0hSKSAlPiUKICB1bmlxdWUoKQoKIyBpZGVudGlmeSBhbGwgU05QcyBvbiBjb250aWdzClNOUHMgPC0gaHdlICU+JQogIGZpbHRlcihDSFIgJWluJSBjb250aWdzJENIUikgJT4lCiAgc2VsZWN0KENIUiwgUE9TKQoKIyBWaWV3KGNvbnRpZ3MpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byB0ZXh0IGZpbGUsIHVzZSBmaWxlIHdpdGggdmNmdG9vbHMgdG8gcmVtb3ZlIHBvc2l0aW9ucyBmcm9tIGRhdGFzZXQgCndyaXRlLnRhYmxlKFNOUHMsIGZpbGUgPSAiZGF0YS9WQ0YvaGV0ZXhjZXNzLmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBTTlBzIHdpdGggZXhjZXNzIGhldGVyb3p5Z29zaXR5IGFuZCBjb250aWdzIHdpdGggbW9yZSB0aGFuIG9uZSBTTlAgdy9leGNlc3MgaGV0ZXJvenlnb3NpdHkuCgpgYGB7YmFzaH0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMSAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL2hldGV4Y2Vzcy5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMSAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTEgLS1taXNzaW5nLXNpdGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMSAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tZ2Vuby1kZXB0aAoKYGBgCgpWaXN1YWxpemUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMTIsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMTEgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMTEiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX0YxMSA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GMTEiKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGxvY19zdGF0c19GMTEpYCBTTlAgc2l0ZXMgYW5kIGByIG5yb3coaW5kX3N0YXRzX0YxMSlgIGluZGl2aWR1YWxzLgoKIyMjIEZpbHRlciAxMjogRmlsdGVyIExRIGluZGl2aWR1YWxzCgpDb21wYXJlIG1lYW4gZGVwdGggYW5kIG51bWJlciBvZiBzaXRlcyBjYWxsZWQgcGVyIGluZGl2aWR1YWwuCgpgYGB7ciBpZGVwdGggc2l0ZXMgdnMgZGVwdGgsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYxMS5pZGVwdGgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBOX1NJVEVTLCB5ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIHNpdGVzIiwgeSA9ICJtZWFuIHJlYWQgZGVwdGgiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKVXNlIGdlbm90eXBlIGRlcHRoIGZpbGUgdG8gaWRlbnRpZnkgaW5kaXZpZHVhbHMgd2l0aCBoaWdoIHZhcmlhbmNlIGluIHJlYWQgZGVwdGggYWNyb3NzIGxvY2kuCgpgYGB7ciB2YXJpYW5jZSBkZXB0aCBpbmRpdmlkdWFsfQoKIyBudW1iZXIgb2YgaW5kaXZpZHVhbHMKbiA8LSBucm93KGluZF9zdGF0c19GMTEpKzEKCiMgcmVhZCBnZW5vdHlwZSBkZXB0aCAmIGNvZGUgdmFsdWVzIDwgNSBhcyBtaXNzaW5nLCByZXRhaW4gb25seSBvbmUgbG9jdXMgcGVyIGNvbnRpZwpnZGVwdGggPC0gcmVhZF90YWJsZTIoImRhdGEvVkNGL0JNQS5GMTEuZ2RlcHRoIikgJT4lCiAgc2VsZWN0KC1QT1MpICU+JQogIGRpc3RpbmN0KENIUk9NLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUKICBnYXRoZXIoa2V5ID0gSU5EViwgdmFsdWUgPSBHREVQVEgsIDI6bikgJT4lCiAgbXV0YXRlKEdERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigtMSwgMCwgR0RFUFRIKSkpICU+JQogIG11dGF0ZShERVBUSCA9IEdERVBUSCkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwxXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwyXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwzXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDw0XFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKE1JU1NJTkcgPSBpZmVsc2UoREVQVEggPT0gMCwgIm1pc3NpbmciLCAiZ2Vub3R5cGVkIikpICU+JQogIG11dGF0ZShHREVQVEhCSU4gPSBjdXQoR0RFUFRILCAKICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMCwgNSwgMTAsIDI1LCA1MCwgMTAwLCA1MDAsIG1heChHREVQVEgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjw1IiwgIjMtMTAiLCAiMTAtMjUiLCAiMjUtNTAiLCAiNTAtMTAwIiwgIjEwMC01MDAiLCAiPjUwMCIpKSkgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKSAlPiUKICBtdXRhdGUoTElCID0gc3RyX3JlcGxhY2VfYWxsKExJQiwgIjFBLioiLCAiQk1BMSIpLAogICAgICAgICBMSUIgPSBzdHJfcmVwbGFjZV9hbGwoTElCLCAiMUIuKiIsICJCTUExIiksCiAgICAgICAgIExJQiA9IHN0cl9yZXBsYWNlX2FsbChMSUIsICIyQS4qIiwgIkJNQTIiKSwKICAgICAgICAgTElCID0gc3RyX3JlcGxhY2VfYWxsKExJQiwgIjJCLioiLCAiQk1BMiIpLAogICAgICAgICBMSUIgPSBzdHJfcmVwbGFjZV9hbGwoTElCLCAiM0EuKiIsICJCTUEzIiksCiAgICAgICAgIExJQiA9IHN0cl9yZXBsYWNlX2FsbChMSUIsICIzQi4qIiwgIkJNQTMiKSkKCmdkZXB0aCA8LSBsZWZ0X2pvaW4oZ2RlcHRoLCBTYW1wbGVJbmZvLCBieSA9ICJTQU1QTEVfSUQiKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBkZXB0aC4KCmBgYHtyIGdlbm90eXBlIGRlcHRoIGhlYXRtYXAgcG9wLCBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MjB9CgojIHdvdWxkIG5lZWQgdG8gam9pbiB3aXRoIFNhbXBsZSBJbmZvIHRvIGdldCBwb3Agc3BlY2lmaWNhdGlvbnMKZ2dwbG90KGdkZXB0aCwgYWVzKHggPSBJTkRWLCB5ID0gQ0hST00pKSArCiAgZ2VvbV90aWxlKGFlcyhmaWxsID0gR0RFUFRIQklOKSkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ2dlbm90eXBlIGRlcHRoJywKICAgICAgICAgICAgICAgICAgICAgZGlzY3JldGUgPSBUUlVFKSArCiAgZmFjZXRfZ3JpZCguIH4gUE9QLCBzcGFjZSA9ICJmcmVlIiwgc2NhbGVzID0gImZyZWUiLCBkcm9wID0gVFJVRSkgKwogIGxhYnMoeCA9ICJpbmRpdmlkdWFsIiwgeSA9ICJsb2N1cyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBkZXB0aCBvZiBpbmRpdmlkdWFscyBncm91cGVkIGJ5IGxpYnJhcnkuCgpgYGB7ciBnZW5vdHlwZSBkZXB0aCBoZWF0bWFwIGxpYiwgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTIwfQoKZ2dwbG90KGdkZXB0aCwgYWVzKHggPSBJTkRWLCB5ID0gQ0hST00pKSArIAogIGdlb21fdGlsZShhZXMoZmlsbCA9IEdERVBUSEJJTikpICsgCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBvcHRpb24gPSAidmlyaWRpcyIsCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnZ2Vub3R5cGUgZGVwdGgnLAogICAgICAgICAgICAgICAgICAgICBkaXNjcmV0ZSA9IFRSVUUpICsKICBmYWNldF9ncmlkKC4gfiBMSUIsIHNwYWNlID0gImZyZWUiLCBzY2FsZXMgPSAiZnJlZSIsIGRyb3AgPSBUUlVFKSArCiAgbGFicyh4ID0gImluZGl2aWR1YWwiLCB5ID0gImxvY3VzIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIGdlbm90eXBlIGRlcHRocyAoYWNyb3NzIGFsbCBpbmRpdmlkdWFscykuCgpgYGB7ciBkaXN0cmlidXRpb24gZ2Vub3R5cGUgZGVwdGhzLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTUuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnRlbXAgPC0gY291bnQoZ2RlcHRoLCBHREVQVEhCSU4pCgpnZ3Bsb3QodGVtcCwgYWVzKHggPSBHREVQVEhCSU4sIHkgPSBuKSkgKwogIGdlb21fYmFyKHN0YXQ9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCklkZW50aWZ5IHZhcmlhbmNlIGluIGRlcHRoIHcvaW4gaW5kaXZpZHVhbHMuCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTl9CgojIGNhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKaWRlcHRoIDwtIGdkZXB0aCAlPiUKICBncm91cF9ieShJTkRWKSAlPiUKICBzdW1tYXJpemUoVE9UQUwgPSBzdW0oREVQVEgpLAogICAgICAgICAgICBNQVggPSBtYXgoREVQVEgpLAogICAgICAgICAgICBNRUFOID0gbWVhbihERVBUSCksCiAgICAgICAgICAgIE1FRElBTiA9IG1lZGlhbihERVBUSCksCiAgICAgICAgICAgIFZBUiA9IHZhcihERVBUSCksCiAgICAgICAgICAgIFNURCA9IHNkKERFUFRIKSkgJT4lCiAgbXV0YXRlKENPRUZGX1ZBUiA9IFNURC9NRUFOLAogICAgICAgICBSQVRJT19NRUFOX01FRElBTiA9IE1FQU4vTUVESUFOKQoKcDEgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBNRUFOLCB5ID0gTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IE1BWCwgeSA9IFRPVEFMKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDMgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBUT1RBTCwgeSA9IFZBUikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiYXV0byIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDQgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKE1FRElBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDUgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKFJBVElPX01FQU5fTUVESUFOKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDYgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKENPRUZGX1ZBUikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMTRiIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBjb2xzPTIpCgpgYGAKCkNvbXBhcmUgZGVwdGgsIG1pc3NpbmcgZGF0YSBhbmQgaW5kaXZpZHVhbCBoZXRlcm96eWdvc2l0eSBsZXZlbHMuCgpgYGB7ciBpc3RhdHMsIGZpZy5oZWlnaHQ9MTgsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmltaXNzIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjExLmltaXNzIikgJT4lCiAgc2VsZWN0KElORFYsIE5fREFUQSwgRl9NSVNTKQoKaXN0YXRzIDwtIGxlZnRfam9pbihpZGVwdGgsIGltaXNzKQoKRmlzIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjExLmhldCIpICU+JQogIHNlbGVjdCgtTl9TSVRFUykKCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaXN0YXRzLCBGaXMpCgpwMSA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IE1FQU4sIHkgPSBGX01JU1MsIGZpbGwgPSBgRmApKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBzaXplID0gMiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IDEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICdGaXMnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gQ09FRkZfVkFSLCB5ID0gTUVBTiwgZmlsbCA9IEZfTUlTUykpICsKIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJyUgbWlzc2luZycsIGRpc2NyZXRlID0gRkFMU0UpICsKICB0aGVtZV9zdGFuZGFyZAoKcDMgPC0gZ2dwbG90KGlzdGF0cywgYWVzKHggPSBgTyhIT00pYCwgeSA9IE1FQU4sIGZpbGwgPSBGX01JU1MpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBzaXplID0gMiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBvcHRpb24gPSAidmlyaWRpcyIsCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnbWVhbiByZWFkIGRlcHRoJywgZGlzY3JldGUgPSBGQUxTRSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IE1FQU4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA1IDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gYEZgLCB5ID0gTUVBTiwgZmlsbCA9IEZfTUlTUykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIHNpemUgPSAyLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICclIG1pc3NpbmcnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA2IDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gYEZgLCB5ID0gQ09FRkZfVkFSLCBmaWxsID0gRl9NSVNTKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJyUgbWlzc2luZycsIGRpc2NyZXRlID0gRkFMU0UpICsKICB0aGVtZV9zdGFuZGFyZAoKcDcgPC0gZ2dwbG90KGlzdGF0cywgYWVzKHggPSBgRmAsIHkgPSBSQVRJT19NRUFOX01FRElBTiwgZmlsbCA9IEZfTUlTUykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIHNpemUgPSAyLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICclIG1pc3NpbmcnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC44LCA0KSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwOCA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IEZfTUlTUykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgoKbTE0YiA8LSBtdWx0aXBsb3QocDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDcsIHA4LCBjb2xzPTIpCgpgYGAKCkZsYWcgbG93IHF1YWxpdHkgaW5kaXZpZHVhbHMKCmBgYHtyfQoKIyBWaWV3KGlzdGF0cykKCkxRX2luZCA8LSBpc3RhdHMgJT4lCiAgIGZpbHRlcihgRmAgPiAuOSB8IGBGYCA8IC0uMjUpICU+JQogICBzZWxlY3QoSU5EVikKCndyaXRlLnRhYmxlKExRX2luZCwgImRhdGEvVkNGL0YxMl9MUS5pbmR2IiwKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKCiMjIyBGaWx0ZXIgMTM6IE1pc3NpbmcgZGF0YSBieSBzYW1wbGUgbG9jYXRpb24KCmBgYHtiYXNoIG1pc3NpbmcgYnkgc2FtcGxlIGxvY2F0fQoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyIC0tcmVtb3ZlIGRhdGEvVkNGL0YxMl9MUS5pbmR2IC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgojIENhbXBlY2hlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQ0FNUCAtLWtlZXAgZGF0YS9WQ0YvQ0FNUC5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0FNUC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0NBTVAgLS1taXNzaW5nLXNpdGUKCiMgQ2hhbmRlbGV1ciBTb3VuZAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0NTIC0ta2VlcCBkYXRhL1ZDRi9DUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9DUyAtLW1pc3Npbmctc2l0ZQoKIyBDb3JwdXMgQ2hyaXN0aSBCYXkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9DQyAtLWtlZXAgZGF0YS9WQ0YvQ0MuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0NDLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQ0MgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBBdGxhbnRpYwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMQSAtLWtlZXAgZGF0YS9WQ0YvRkxBLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEEgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIFNvdXRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxHUyAtLWtlZXAgZGF0YS9WQ0YvRkxHUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvRkxHUy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0ZMR1MgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIE5vcnRoIAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMR04gLS1rZWVwIGRhdGEvVkNGL0ZMR04uaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0ZMR04ucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEdOIC0tbWlzc2luZy1zaXRlCgojIExvdWlzaWFuYQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0xBIC0ta2VlcCBkYXRhL1ZDRi9MQS5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9MQSAtLW1pc3Npbmctc2l0ZQoKIyBNaXNzaXNzaXBwaSBTb3VuZCAKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9NSVNTIC0ta2VlcCBkYXRhL1ZDRi9NSVNTLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NSVNTLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvTUlTUyAtLW1pc3Npbmctc2l0ZQoKIyBNb2JpbGUgQmF5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvTUIgLS1rZWVwIGRhdGEvVkNGL01CLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NQi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL01CIC0tbWlzc2luZy1zaXRlCgpgYGAKCkNvbXBhcmUgbWlzc2luZyBkYXRhIHBlciBzYW1wbGUgcmVnaW9uOgoKYGBge3IgY29tcGFyZSBtaXNzaW5nIGJ5IGxvY2F0LCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcG9wcyB0byBsb29wIG92ZXIKcG9wIDwtIHVuaXF1ZShJbmRfUkFXJFBPUCkKCmxvY19taXNzaW5nIDwtIGxpc3QoKQoKIyBpbXBvcnQgbWlzc2luZyBkYXRhIHBlciBsb2N1cwpmb3IgKHAgaW4gcG9wKSB7CiAgCiAgbG9jX21pc3NpbmdbW3BdXSA8LSByZWFkX2RlbGltKHBhc3RlKCJkYXRhL1ZDRi8iLCBwLCAiLmxtaXNzIiwgc2VwID0gIiIpLCBkZWxpbSA9ICJcdCIpICU+JQogICAgc2VsZWN0KENIUiwgUE9TLCBGX01JU1MpICU+JQogICAgbXV0YXRlKFBPUCA9IHApCiAgCn0KCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCBhbGwgaW5mb3JtYXRpb24KbG9jX21pc3NpbmcgPC0gbGRwbHkobG9jX21pc3NpbmcsIGRhdGEuZnJhbWUpCgpnZ3Bsb3QobG9jX21pc3NpbmcsIGFlcyh4ID0gRl9NSVNTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjA1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4xNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBsb2N1cyIpICsKICBzY2FsZV95X3NxcnQoKSArCiAgZmFjZXRfZ3JpZChQT1AgfiAuKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggc2FtcGxlIGxvY2F0aW9uICg+IDE1ICUgbWlzc2luZyBkYXRhIGluIGEgZ2l2ZW4gbG9jYXRpb24pLgoKYGBge3J9CiMgaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggcmVnaW9uClNOUHMgPC0gZmlsdGVyKGxvY19taXNzaW5nLCBGX01JU1MgPiAwLjE1KSAKCmNvdW50KFNOUHMsIFBPUCkKCmNvbnRpZ3MgPC0gU05QcyAlPiUKICBkaXN0aW5jdChDSFIpCgpTTlBzIDwtIFNOUHMgJT4lCiAgc2VsZWN0KENIUiwgUE9TKQoKIyBXcml0ZSBjb250aWcvcG9zaXRpb24gdG8gdGV4dCBmaWxlLCB1c2UgZmlsZSB3aXRoIHZjZnRvb2xzIHRvIHJlbW92ZSBwb3NpdGlvbnMgZnJvbSBkYXRhc2V0IAp3cml0ZS50YWJsZShTTlBzLCBmaWxlID0gImRhdGEvVkNGL0xRX0YxMy5sb2NpIiwgCiAgICAgICAgICAgIGNvbC5uYW1lcz0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQpgYGAKClJlbW92ZSBsb2NpIGZyb20gZGF0YSBzZXQ6CgpgYGB7YmFzaH0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMyAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL0xRX0YxMy5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEzLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMyAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1nZW5vLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1zaW5nbGV0b25zCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1pbmR2LWZyZXEtYnVyZGVuCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1mcmVxCgpgYGAKCkNvbXBhcmUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMTMsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMTMgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMTMiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFLCBleHRyYSA9ICJtZXJnZSIpCgpsb2Nfc3RhdHNfRjEzIDwtIHJlYWQubG9jLnN0YXRzKGRpciA9ICJkYXRhL1ZDRiIsIHZjZiA9ICJCTUEuRjEzIikKCiMgcGxvdCBtaXNzaW5nIGRhdGEgcGVyIGluZHYgLS0tLQpwMSA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YxMywgYWVzKHggPSBNSVNTX0JNQS5GMTMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtaXNzaW5nIGRhdGEgcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCByZWFkIGRlcHRoIHBlciBpbmR2IC0tLS0KcDIgPC0gZ2dwbG90KGluZF9zdGF0c19GMTMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjEzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjEzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYxMywgeSA9IE1JU1NfQk1BLkYxMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgcGVyIGluZHYgLS0tLQpwNCA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YxMywgYWVzKHggPSBGaXNfQk1BLkYxMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnA1IDwtIGdncGxvdChpbmRfc3RhdHNfRjEzLCBhZXMoeCA9IEZpc19CTUEuRjEzLCB5ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IEZpcyB2cyBtZWFuIGRlcHRoIHBlciBpbmR2IC0tLS0KcDYgPC0gZ2dwbG90KGluZF9zdGF0c19GMTMsIGFlcyh4ID0gRmlzX0JNQS5GMTMsIHkgPSBNRUFOX0RFUFRIX0JNQS5GMTMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihGaXNfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IiwgeSA9ICJtZWFuIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgoKIyBwbG90IGRpc3RyaWJ1dGlvbiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIC0tLS0KcDcgPC0gZ2dwbG90KGxvY19zdGF0c19GMTMsIGFlcyh4ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjEzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiJSBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1lYW4gcmVhZCBkZXB0aCAtLS0tCnA4IDwtIGdncGxvdChsb2Nfc3RhdHNfRjEzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYxMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19GMTMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjEzLCB5ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuRjEzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIFNOUCBxdWFsaXR5IC0tLS0Kc2l0ZV9xdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMTMubHF1YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoUFJPQiA9IDEwXigtUVVBTC8xMCkpCgp0ZW1wIDwtIGRhdGEuZnJhbWUobG9jX3N0YXRzX0YxMyRNRUFOX0RFUFRIX0JNQS5GMTMsIHNpdGVfcXVhbCRRVUFMKSAlPiUKICByZW5hbWUoZGVwdGggPSBsb2Nfc3RhdHNfRjEzLk1FQU5fREVQVEhfQk1BLkYxMywgcXVhbCA9IHNpdGVfcXVhbC5RVUFMKQoKcDEwIDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oZGVwdGgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4ocXVhbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgbG9jdXMiLCB5ID0gIlNOUCBxdWFsaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnRlbXAgPC0gbG9jX3N0YXRzX0YxMyAlPiUKICBjb3VudChDSFIpCgpwMTEgPC0gbGVmdF9qb2luKHRlbXAsIGxvY19zdGF0c19GMTMpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IE1FQU5fREVQVEhfQk1BLkYxMykpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyIsIHkgPSAibWVhbiBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEyIDwtIGxvY19zdGF0c19GMTMgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm0xNSA8LSBtdWx0aXBsb3QocDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDcsIHA4LCBwOSwgcDEwLCBwMTEsIHAxMiwgY29scz0yKQoKYGBgCgpDb21wYXJlIG51bWJlciBvZiBjb250aWdzIHZzIG51bWJlciBvZiBTTlBzLgoKYGBge3J9CgojIG51bWJlciBvZiBTTlBzCm5yb3cobG9jX3N0YXRzX0YxMykKCiMgbnVtYmVyIG9mIGNvbnRpZ3MgaW4gZGF0YSBzZXQKY29udGlncyA8LSBsb2Nfc3RhdHNfRjEzICU+JQogIGRpc3RpbmN0KENIUikKCm5yb3coY29udGlncykKCmBgYAoKTWVhbiBudW1iZXIgb2YgU05QcyBwZXIgY29udGlnIGlzIGByIG5yb3cobG9jX3N0YXRzX0YxMykvbnJvdyhjb250aWdzKWAuCgpgYGB7cn0KCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaW5kX3N0YXRzX3JhdywgaW5kX3N0YXRzX0YxMykKCmBgYAoKCiMjIEZpbmFsIHRocmVzaG9sZHMgdmFsdWVzIGZvciBmaWx0ZXJlZCBkYXRhIHNldCBCTUE6CgoqIG1pbmltdW0gc2VxdWVuY2UgcXVhbGl0eSAobWluUSk6IDIwCiogbWluaW11bSBnZW5vdHlwZSBxdWFsaXR5IChtaW5HUSk6IDIwCiogbWluaW11bSBnZW5vdHlwZSBjYWxsIHJhdGUgcGVyIGxvY3VzIChnZW5vKTogOTAlCiogbWluaW11bSBnZW5vdHlwZSBkZXB0aCAobWluRCk6IDUKKiBtYXhpbXVtIG1pc3NpbmcgZGF0YSBwZXIgaW5kaXZpZHVhbCAobWlzc0luZCk6IDI1JQoqIG1lYW4gbWluaW11bSBkZXB0aCBwZXIgbG9jdXMgKG0tbWluRCk6IDE1CiogbWVhbiBtYXhpbXVtIGRlcHRoIChtLW1pbkQpOiAzMDAKKiBkRG9jZW50IGZpbHRlcnMgcnVuIGZvciBhbGxlbGljIGJhbGFuY2UsIG1hcHBpbmcgcXVhbGl0eSwgc3RyYW5kZWRuZXNzIGFuZCBwYWlyZWQgc3RhdHVzLCBkZXB0aC9xdWFsaXR5IHJhdGlvCiogSW5kZWxzIHJlbW92ZWQgZnJvbSBkYXRhIHNldAoqIG1pbmltdW0gZ2Vub3R5cGUgY2FsbCByYXRlIGJ5IHBvcHVsYXRpb246IDg1JQoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhsb2Nfc3RhdHNfRjEzKWAgU05QIHNpdGVzIG9uIGByIG5yb3coY29udGlncylgIGFuZCBgciBucm93KGluZF9zdGF0c19GMTMpYCBpbmRpdmlkdWFscy4KCiMgSGFwbG90eXBpbmcKCiMjIFByZXAgZm9yIGhhcGxvdHlwaW5nCgpDcmVhdGUgbGlzdCBvZiBpbmRpdmlkdWFscyByZXRhaW5lZCBpbiBmaW5hbCB2Y2YgZmlsZToKCkNoYW5nZSBzbyB0aGF0IG5ldyBmaWxlIGlzIHByaW50ZWQgaW50byBIYXBsb3R5cGluZy90ZW1wIGZvbGRlcgoKYGBge2Jhc2h9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2ZzYW1wbGVuYW1lcyBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLnJlY29kZS52Y2YgPiBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmluZGl2aWR1YWxzCgpgYGAKClVzZSBgQk1BLUJNQS5pbmRpdmlkdWFsc2AgdG8gY3JlYXRlIGBwb3BtYXBgIGFzIGEgdGFiLXNlcGFyYXRlZCBmaWxlIG9mIGluZGl2aWR1YWxzIGFuZCB0aGVpciBwb3B1bGF0aW9uIGRlc2lnbmF0aW9uLCB3aXRoIG9uZSBpbmRpdmlkdWFsIHBlciBsaW5lIChtYWtlIHN1cmUgVU5JWCBmb3JtYXQpLiBUaGlzIGZpbGUgaXMgbmVlZGVkIHRvIHdyaXRlIHRoZSBnZW5lcG9wIGZpbGUsIGlmIG5vdCBwcm92aWRlZCB0aGUgc2NyaXB0IHdpbGwgcnVuIHRocm91Z2ggdGhlIHByb2Nlc3MgYnV0IG5vdCB3cml0ZSBhIGdlbmVwb3AgZmlsZSBhbmQgcGxhY2UgaW50byBzYW1lIGZvbGRlciBgcmFkX2hhcGxvdHlwZXIucGxgIHdpbGwgYmUgcnVuIGZyb20uCgpgYGB7cn0KCnBvcG1hcCA8LSByZWFkLnRhYmxlKCJkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmluZGl2aWR1YWxzIiwgCiAgICAgICAgICAgICAgICAgICAgIGNvbC5uYW1lcyA9ICJJTkRWIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiUE9QIiwgIkxJQiIsICJJRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFLCBleHRyYSA9ICJtZXJnZSIpICU+JQogIHNlbGVjdChJTkRWLCBQT1ApCgp3cml0ZS50YWJsZShwb3BtYXAsICJkYXRhL0hhcGxvdHlwaW5nL3RlbXAvcG9wbWFwIiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKUGxhY2UgYWxsIG5lY2Vzc2FyeSBmaWxlcyBpbiBgZGF0YS9IYXBsb3R5cGluZy90ZW1wYCBkaXJlY3RvcnkgKGJhbSwgZmFzdHEsIHJlZmVyZW5jZS5mYXN0YSwgdmNmLWZpbGUpCgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMS8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0xLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMi8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0yLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMy8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0zLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCgpgYGAKCiMjIFJ1biBIYXBsb3R5cGVyCgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgZGlmZmljdWx0eSBydW5uaW5nIGZyb20gUgpyYWRfaGFwbG90eXBlci5wbCAtdiBCTUEucmVjb2RlLnZjZiAtciByZWZlcmVuY2UuZmFzdGEgLXggMzUgLWQgMTAgLXogMyAtbSAuMjUgLWcgQk1BLmdlbiAtcCBwb3BtYXAKCmBgYAoKQ29weSBmaWxlcyBmb3IgYW5hbHlzaXMgaW50byBgZGF0YS9IYXBsb3R5cGluZy9gLWZvbGRlcgoKYGBge2Jhc2h9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCnJtICouZnEuZ3oKcm0gKi5iYW0qCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wL2luZF9zdGF0cy5vdXQgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvSGFwbG90eXBpbmcvCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wL3N0YXRzLm91dCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy8KCmNwIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmdlbiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy8KCmBgYAoKIyBIYXBsb3R5cGUgZmlsdGVyaW5nCgojIyBPdmVydmlldyBvZiBoYXBsb3R5cGluZyBzdWNjZXNzCgpDb21wYXJpc29uIG9mIHRoZSBudW1iZXIgb2YgbG9jaSB0aGF0IHdlcmUgZmlsdGVyZWQgZHVlIHRvIGV4Y2VzcyBudW1iZXIgb2YgbWlzc2luZyBkYXRhIG9yIHN1c3BlY3RlZCBwYXJhbG9ncyBkdXJpbmcgdGhlIGhhcGxvdHlwaW5nIHByb2Nlc3MgdG8gdGhvc2UgdGhhdCBwYXNzZWQuIEhhcGxvdHllciB3YXMgcnVuIHdpdGhvdXQgYW55IHRocmVzaG9sZCB2YWx1ZXMgKG90aGVyIHRoYW4gZGVmYXVsdCB2YWx1ZXMpLiBUaGUgZ2VuZXBvcCBmaWxlIG9ubHkgY29udGFpbnMgbG9jaSB0aGF0IHBhc3NlZCBoYXBsb3R5cGluZyBzdGFnZS4KCmBgYHtyIGltcG9ydCBzdGF0cy5vdXQgZmlsZSwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgaW1wb3J0IHN0YXRzIGZpbGVzIGdlbmVyYXRlZCBieSBoYXBsb3R5cGVyCmhhcF9zdGF0cyA8LSByZWFkLmhhcC5zdGF0cygiZGF0YS9IYXBsb3R5cGluZy9zdGF0cy5vdXQiKQoKCgpoYXBfaW5kX3N0YXRzIDwtIHJlYWQuZGVsaW0oImRhdGEvSGFwbG90eXBpbmcvaW5kX3N0YXRzLm91dCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCnRlbXAgPC0gaGFwX2luZF9zdGF0cyAlPiUKICByZW5hbWUoSU5EViA9IEluZCkKCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaXN0YXRzLCB0ZW1wKQoKIyB2aWV3IGNvbXBhcmlzb24gb2YgZmlsdGVyZWQgdnMuIHBhc3NlZCBsb2NpCnBsb3QuZmlsdGVyLnN0YXR1cyhoYXBfc3RhdHMpCgpgYGAKClJlbW92ZSBmaWx0ZXJlZCBsb2NpIGZyb20gZGF0YSBzZXQuCgpgYGB7cn0KCmNvdW50KGhhcF9zdGF0cywgU3RhdHVzID09ICJGSUxURVJFRCIpCgpoYXBfc3RhdHMgPC0gcmVtb3ZlLmZpbHRlcmVkLmhhcHMoaGFwX3N0YXRzKQoKYGBgCgpgciBucm93KGhhcF9zdGF0cylgIGxvY2kgcGFzc2VkIGhhcGxvdHlwaW5nIHByb2Nlc3MuCgpgYGB7ciBwbG90IHN0YXRzLm91dCBmaWxlLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcGxvdC5oYXAuc3RhdHMoaGFwX3N0YXRzKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGhhcF9pbmRfc3RhdHMpYCBpbmRpdmlkdWFsczoKCmBgYHtyIHBsb3QgaW5kLnN0YXRzLm91dCBmaWxlLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcGxvdC5pbmQuaGFwLnN0YXRzKGhhcF9pbmRfc3RhdHMpCgpgYGAKCiMjIElkZW50aWZ5IHRocmVzaG9sZCB2YWx1ZXMgdG8gZmlsdGVyIGRhdGEgc2V0CgojIyMgUHJvcG9ydGlvbiBvZiBpbmRpdmlkdWFscyBoYXBsb3R5cGVkCgpgYGB7ciBwcm9wIGluZHYgaGFwbG90eXBlZCwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGhhcF9zdGF0cyA8LSByZWFkLmhhcC5zdGF0cygiZGF0YS9IYXBsb3R5cGluZy9zdGF0cy5vdXQiKQoKcDEgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBQcm9wX0hhcGxvdHlwZWQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAyNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUHJvcF9IYXBsb3R5cGVkLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC45KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInByb3BvcnRpb24gaW5kaXZpZHVhbHMgaGFwbG90eXBlZCIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDIgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBQcm9wX0hhcGxvdHlwZWQsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihQcm9wX0hhcGxvdHlwZWQsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJwcm9wb3J0aW9uIGluZGl2aWR1YWxzIGhhcGxvdHlwZWQiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QoaGFwX3N0YXRzLCBhZXMoeCA9IFByb3BfSGFwbG90eXBlZCwgeSA9IGBMb3dfQ292Lkdlbm9fRXJyYCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKFByb3BfSGFwbG90eXBlZCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInByb3BvcnRpb24gaW5kaXZpZHVhbHMgaGFwbG90eXBlZCIsIHkgPSAibG93IGNvdmVyYWdlIGVycm9yIikgKwogIHRoZW1lX3N0YW5kYXJkCgptdWx0aXBsb3QocDEsIHAyLCBwMywgY29scyA9IDMpCgpgYGAKCkZsYWcgbG9jaSBzdWNjZXNzZnVsbHkgaGFwbG90eXBlZCBpbiA8IDkwJSBvZiBpbmRpdmlkdWFscy4KCmBgYHtyIGZpbHRlciBsb2NpIGdlbm90eXBlIGNhbGwgcmF0ZSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbnVtYmVyIG9mIGxvY2kgY2FsbGVkIGluID45NSUgaW5kaXZpZHVhbHMKY291bnQoaGFwX3N0YXRzLCBQcm9wX0hhcGxvdHlwZWQgPCAwLjkpCgojIGNyZWF0ZSB2ZWN0b3Igb2YgbG9jaSB0byByZW1vdmUgKGNob29zZSBjdXQtb2ZmKQpQcm9wX0hhcGxvdHlwZWQgPC0gZmlsdGVyLmxvY2kucHJvcF9oYXBsb3R5cGVkKGhhcF9zdGF0cywgMC45KQoKYGBgCgpgciBsZW5ndGgoUHJvcF9IYXBsb3R5cGVkKWAgbG9jaSB3ZXJlIGZsYWdnZWQgYXMgZ2Vub3R5cGUgY2FsbCByYXRlIDwgMC45LgoKIyMjIFBvc3NpYmxlIHBhcmFsb2dzIHBlciBsb2N1cwoKTG9jaSBhcmUgZmxhZ2dlZCBhcyBwb3NzaWJsZSBwYXJhbG9ncyBmb3IgYW4gaW5kaXZpZHVhbHMgd2hlbiBtb3JlIHRoYW4gdGhlIGV4cGVjdGVkIG51bWJlciBvZiBoYXBsb3R5cGVzIGJhc2VkIG9uIHRoZSBTTlAgZ2Vub3R5cGUgY2FsbCAoaG9tb3p5Z290ZSwgaGV0ZXJvenlnb3RlKSBhcmUgZGV0ZWN0ZWQuCgpgYGB7ciBwb3NzIHBhcmFsb2dzIHBlciBsb2N1cywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gUG9zc19QYXJhbG9nKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMiwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUG9zc19QYXJhbG9nLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX2luZF9zdGF0cykqMC4wMSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAicG9zc2libGUgcGFyYWxvZ3MgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCjEgJSBvZiBpbmRpdmlkdWFsczogYHIgbnJvdyhoYXBfaW5kX3N0YXRzKSowLjAxYCAKNSAlIG9mIGluZGl2aWR1YWxzOiBgciBucm93KGhhcF9pbmRfc3RhdHMpKjAuMDVgIAoKRmxhZyBsb2NpIHRoYXQgYXJlIGZsYWdnZWQgYXMgcG90ZW50aWFsIHBhcmFsb2dzIGluIDUgb3IgbW9yZSBpbmRpdmlkdWFscy4KNApgYGB7ciBmaWx0ZXIgbG9jaSBwYXJhbG9nc30KCiMgbnVtYmVyIG9mIGxvY2kgd2l0aCBQb3NzX1BhcmFsb2dzCmNvdW50KGhhcF9zdGF0cywgUG9zc19QYXJhbG9nID4gNCkKCiMgY3JlYXRlIHZlY3RvciBvZiBsb2NpIHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpClBvc3NfUGFyYWxvZ3MgPC0gZmlsdGVyLmxvY2kucGFyYWxvZ3MoaGFwX3N0YXRzLCA0KQoKYGBgCgpgciBsZW5ndGgoUG9zc19QYXJhbG9ncylgIGxvY2kgd2VyZSBmbGFnZ2VkIGFzIHBvc3NpYmxlIHBhcmFsb2dzLgoKIyMjIE51bWJlciBvZiBTTlBzICYgSGFwbG90eXBlcyBwZXIgbG9jdXMKCkVhY2ggbG9jdXMgdmFyaWVzIGluIHRoZSBudW1iZXIgb2YgU05QcyBkZXRlY3RlZCB3aGljaCBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgaGFwbG90eXBlcyBleHBlY3RlZCBpbiB0aGF0IHBvcHVsYXRpb24uIAoKYGBge3Igbm8gU05QcywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gU2l0ZXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihTaXRlcywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDI1KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm51bWJlciBvZiBTTlBzIHBlciBjb250aWciKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKRmlsdGVyaW5nIGxvY2kgYmFzZWQgb24gbnVtYmVyIG9mIFNOUHMgY29udGFpbmVkIG9uIHRoYXQgbG9jdXMgY291bGQgYmlhcyB0aGUgZGF0YSBzZXQgYXMgbG9jaSB3aXRoIGhpZ2ggcmVjb21iaW5hdGlvbiBtYXkgYmUgcmVtb3ZlZC4gT24gdGhlIG90aGVyIGhhbmQsIGFzc3VtaW5nIGFuIGFwcHJveGltYXRlIGxlbmd0aCBvZiAyNTAgYnAgbG9jaSB3aXRoIG1vcmUgdGhhbiBgciAyNTAqMC4xYCBTTlBzIHdvdWxkIG1lYW4gdGhhdCAxMCUgb2YgYmFzZXMgYXJlIGEgcG9seW1vcnBoaXNtcy4KCmBgYHtyIHNpdGVzIHZzIHBhcmFsb2dzLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD04fQoKcDEgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBIYXBsb3R5cGVzLCB5ID0gUG9zc19QYXJhbG9nKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGxhYnMoeCA9ICJuby4gaGFwbG90eXBlcyIsIHkgPSAicG9zc2libGUgcGFyYWxvZ3MiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gU2l0ZXMsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgbGFicyh4ID0gIm5vLiBvZiBzaXRlcyIsIHkgPSAiICIpICsKICB0aGVtZV9zdGFuZGFyZAogIAptdWx0aXBsb3QocDEsIHAyLCBjb2xzID0gMikKCmBgYAoKSWRlbnRpZnkgbnVtYmVyIG9mIGhhcGxvdHlwZXMgbG9jaSB3aXRoID4gMzUgU05QIHNpdGVzLgoKYGBge3IgZmlsdGVyIG5vIG9mIFNOUHN9Cgpjb3VudChoYXBfc3RhdHMsIFNpdGVzID4gMzUpCgpOb1NOcHMgPC0gZmlsdGVyLmxvY2kubm9TTlBzKGhhcF9zdGF0cywgMzUpCgpgYGAKCmByIGxlbmd0aChOb1NOcHMpYCBsb2NpIHdlcmUgZmxhZ2dlZC4KCkFzc3VtaW5nIHRoYXQgbXV0YXRpb24gaXMgdGhlIG9ubHkgbWVjaGFuaXNtIHJlc3VsdGluZyBpbiBuZXcgaGFwbG90eXBlcywgdGhlIG1heGltdW0gZXhwZWN0ZWQgbnVtYmVyIG9mIGhhcGxvdHlwZXMgcGVyIGxvY3VzIGlzIG51bWJlciBvZiBTTlBzIE4gKyAxLgoKYGBge3IgeHRyYSBoYXBsb3R5cGVzLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpwMSA8LSBnZ3Bsb3QoaGFwX3N0YXRzLCBhZXMoeCA9IEhhcGxvdHlwZXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihIYXBsb3R5cGVzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoSGFwbG90eXBlcywgLjk5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiIyBoYXBsb3R5cGVzIHBlciBsb2N1cyIsIHkgPSAiIyBsb2NpIikgKwogIHRoZW1lX3N0YW5kYXJkCgp0ZW1wIDwtIGhhcF9zdGF0cyAlPiUKICBzZWxlY3QoTG9jdXMsIFNpdGVzLCBIYXBsb3R5cGVzLCBQcm9wX0hhcGxvdHlwZWQsIExvd19Db3YuR2Vub19FcnIsIFBvc3NfUGFyYWxvZykgJT4lCiAgbXV0YXRlKGV4cF9zaXRlcyA9IFNpdGVzICsgMSkgJT4lCiAgbXV0YXRlKHh0cmEgPSBIYXBsb3R5cGVzIC0gU2l0ZXMpCgpwMiA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSBTaXRlcywgeSA9IFBvc3NfUGFyYWxvZykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIFNOUCBzaXRlcyBwZXIgbG9jdXMiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSBTaXRlcywgeSA9IHh0cmEpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxMCwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDI1LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIiMgU05QIHNpdGVzIHBlciBsb2N1cyIsIHkgPSAiIyBleHRyYSBoYXBsb3R5cGVzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSB4dHJhLCB5ID0gUHJvcF9IYXBsb3R5cGVkKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjksIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGV4dHJhIGhhcGxvdHlwZXMiLCB5ID0gInByb3BvcnRpb24gb2YgaW5kdiBoYXBsb3R5cGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNSA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSB4dHJhLCB5ID0gTG93X0Nvdi5HZW5vX0VycikpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDI1LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIiMgZXh0cmEgaGFwbG90eXBlcyIsIHkgPSAicG90ZW50aWFsIGdlbm90eXBpbmcgZXJyb3IiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA2IDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IHh0cmEsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGV4dHJhIGhhcGxvdHlwZXMiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMjEgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIGNvbHMgPSAyKQoKYGBgCgpBZ2FpbiwgcmVtb3ZpbmcgbG9jaSB3aXRoIHVuZXhwZWN0ZWRseSBoaWdoIG51bWJlcnMgb2YgaGFwbG90eXBlcyBtYXkgYmlhcyB0aGUgZGF0YSBzZXQsIGFzIGxvY2kgd2l0aCBlLmcuIGhpZ2ggcmVjb21iaW5hdGlvbiBtYXkgYmUgcmVtb3ZlZCBmcm9tIHRoZSBkYXRhIHNldC4KCmBgYHtyIGZpbHRlciBubyBvZiBoYXBsb3R5cGVzfQoKY291bnQodGVtcCwgeHRyYSA+PSA1MCkKCiMgY3JlYXRlIHZlY3RvciBvZiBsb2NpIHRvIHJlbW92ZQpOb0hhcHMgPC0gZmlsdGVyKHRlbXAsIHh0cmEgPj0gNTApIAoKTm9IYXBzIDwtIE5vSGFwcyRMb2N1cwoKYGBgCgpgciBsZW5ndGgoTm9IYXBzKWAgbG9jaSB3ZXJlIGZsYWdnZWQgZm9yIGV4Y2Vzc2l2ZSBudW1iZXIgb2YgaGFwbG90eXBlcyBjb21wYXJlZCB0byB0aGUgbnVtYmVyIG9mIFNOUHMgYXQgdGhhdCBsb2N1cy4KCiMjIyBMb3cgQ292ZXJhZ2UvR2Vub3R5cGluZyBFcnJvcgoKQWZ0ZXIgY29tYmluaW5nIFNOUHMgb24gdGhlIHNhbWUgY29udGlnIGR1cmluZyB0aGUgaGFwbG90eXBpbmcgcHJvY2VzcywgaXQgaXMgcG9zc2libGUgdG8gb2JzZXJ2ZSBmZXdlciB0aGFuIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgaGFwbG90eXBlcyBiYXNlZCBvbiB0aGUgZ2Vub3R5cGUgY2FsbCAoaGV0ZXJvenlnb3RlL2hvbW96eWdvdGUpLiBXaGVuIHRoaXMgb2NjdXJzLCB0aGF0IGdlbm90eXBlIGlzIGNvZGVkIGFzIG1pc3NpbmcuIEZvciBlYWNoIGxvY3VzIHRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgZm9yIHdoaWNoIGlzIGl0IGZsYWdnZWQgYXMgYSBwb3RlbnRpYWwgYSBwb3RlbnRpYWwgZ2Vub3R5cGluZyBlcnJvciBvciBzdWZmZXJpbmcgZnJvbSBudWxsIGFsbGVsZXMgZHVlIHRvIGxvdyBjb3ZlcmFnZSBkZXRlY3RlZCBmb3IgYSBnaXZlbiBsb2N1cyBpcyByZWNvcmRlZC4gCgpgYGB7ciBsb3cgY292IGdlbm90eXBnIGVycm9yLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBMb3dfQ292Lkdlbm9fRXJyKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTG93X0Nvdi5HZW5vX0VyciwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IChucm93KGhhcF9pbmRfc3RhdHMpKjAuMDUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInBvdGVudGlhbCBnZW5vdHlwaW5nIGVycm9yIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCkxvY2kgd2l0aCBwcm9ub3VuY2VkIHBhdHRlcm5zIG9mIGdlbm90eXBpbmcgZXJyb3IgbGlrZWx5IGR1ZSB0byBsb3cgY292ZXJhZ2Ugd2lsbCBoYXZlIGxvdyBzdWNjZXNzIHJhdGUgZm9yIGdlbm90eXBpbmcsIGkuZS4gdGhleSB3aWxsIGJlIGNhdWdodCBpbiBtaXNzaW5nIGRhdGEgZmlsdGVycy4gQ292ZXJhZ2UgaXNzdWVzIGFyZSBsaWtlbHkgZ2Vub3R5cGUgc3BlY2ZpYzsgcHJldmlvdXMgZmlsdGVycyBoYXZlIHRhcmdldGVkIGxvY2kgYW5kIGluZGl2aWR1YWxzIHdpdGggaGlnaCB2YXJpYW5jZSBpbiBjb3ZlcmFnZSBhbmQgc3VzcGVjdCBnZW5vdHBlcyBoYXZlIGJlZW4gY29kZWQgYXMgbWlzc2luZywgaS5lLiB0aGlzIGZpbHRlciBuZWVkIG5vdCBiZSB2ZXJ5IGNvbnNlcnZhdGl2ZSwgcmVnYXJkbGVzcywgbG9jaSB0aGF0IGFyZSByZXBlYXRlZGx5IGJlaW5nIGZsYWdnZWQgYXMgcHJvYmxlbWF0aWMgc2hvdWxkIGJlIHJlbW92ZWQuCgpgYGB7ciBmaWx0ZXIgbG93IGNvdmVyYWdlL2dlbm90eXBpbmcgZXJyb3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIHN1bW1hcnkgb2YgY291bnQgb2YgcG9zc2libGUgZ2Vub3R5cGluZyBlcnJvcnMKY291bnQoaGFwX3N0YXRzLCBMb3dfQ292Lkdlbm9fRXJyID4gMTApCgojIGNyZWF0ZSB2ZWN0b3Igb2YgbG9jaSB0byByZW1vdmUKR2Vub19FcnIgPC0gZmlsdGVyLmxvY2kuZ2Vub19lcnIoaGFwX3N0YXRzLCAxMCkKCmBgYAoKYHIgbGVuZ3RoKEdlbm9fRXJyKWAgbG9jaSB3ZXJlIGZsYWdnZWQgYXMgcG90ZW50aWFsbHkgYWZmZWN0ZWQgYnkgZ2Vub3R5cGluZyBlcnJvci4KCiMjIyBGbGFnIHByb2JsZW1hdGljIGluZGl2aWR1YWxzCgpMb2NpIHRoYXQgYXJlIG5vdCBzdWNjZXNzZnVsbHkgaGFwbG90eXBlZCBpbiBhbiBpbmRpdmlkdWFsIGR1ZSB0byBtaXNzaW5nIGRhdGEsIGNvbXBsZXggbG9jdXMsIGhhcGxvdHlwZWQgZ2Vub3R5cGUgaXMgaGlnaGVyL2xvd2VyIHRoYW4gU05QIGhhcGxvdHlwZSBpbiBhIGdpdmVuIGluZGl2aWR1YWwgYXJlIGNvZGVkIGFzIG1pc3NpbmcgZm9yIHRoYXQgaW5kaXZpZHVhbC4gUHJvYmxlbWF0aWMgaW5kaXZpZHVhbCBjYW4gYmUgaWRlbnRpZmllZCBhcyBoYXZpbmcgYSBoaWdoIHByb3BvcnRpb24gb2YgbWlzc2luZyBkYXRhLgoKKipJbmRpdmlkdWFscyB3aXRoIGxvdyBwcm9wb3J0aW9uIG9mIHN1Y2Nlc3NmdWxseSBoYXBsb3R5cGVkIGxvY2kqKgoKYGBge3IgbWlzc2luZyBpbmR2LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9pbmRfc3RhdHMsIGFlcyh4ID0gUHJvcF9TdWNjZXNzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUHJvcF9TdWNjZXNzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC43NSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJwcm9wb3J0aW9uIGxvY2kgc3VjY2Vzc2Z1bGx5IGhhcGxvdHlwZWQiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKUHJvYmxlbSBpbmRpdmlkdWFscyBjYW4gYmUgaWRlbnRpZmllZCBieSBjaG9vc2luZyBhIGN1dC1vZmYgdmFsdWUgZm9yIHRoZSBtaW5pdW0gcHJvcG9ydGlvbiBvZiBzdWNlc3NmdWxseSBoYXBsb3R5cGVkIGxvY2kgYW5kIGV4Y2x1ZGluZyBpbmRpdmlkdWFscyBiZWxvdyB0aGF0IHRocmVzaG9sZCB2YWx1ZS4gUmVtb3ZpbmcgbG9jaSB3aXRoIGxvdyBoYXBsb3R5cGluZyBzdWNjZXNzIHdpdGggZGVjcmVhc2UgdGhlIGFtb3VudCBvZiBtaXNzaW5nIGRhdGEuIFRoZXJlZm9yZSwgZmluYWwgbWlzc2luZyBkYXRhIGN1dC1vZmZzIHNob3VsZCBiZSBhcHBsaWVkICphZnRlciogcmVtb3ZpbmcgdGhvc2UgbG9jaSBmcm9tIHRoZSBkYXRhIHNldCwgdGhvdWdoIGl0IGlzIGltcG9ydGFudCB0byBmbGFnIHBvdGVudGlhbGx5IHByb2JsZW1hdGljIGluZGl2aWR1YWxzIGJhc2VkIG9uIHRoZWlyIGhhcGxvdHlwaW5nIHN0YXRzIGF0IHRoaXMgcG9pbnQuCgpgYGB7ciBmaWx0ZXIgc3VjY2VzcyBoYXBsb3R5cGVkIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgUHJvcF9TdWNjZXNzIDwgLjc1KQoKIyBjcmVhdGUgdmVjdG9yIG9mIGluZHYgdG8gcmVtb3ZlIChjaG9vc2UgY3V0LW9mZikKUHJvcFN1Y2Nlc3NJbmQgPC0gZmlsdGVyLmluZC5wcm9wX3N1Y2Nlc3MoaGFwX2luZF9zdGF0cywgLjc1KQoKd3JpdGUudGFibGUoUHJvcFN1Y2Nlc3NJbmQsICJkYXRhL1BPUEdFTi9wcm9wU3VjYy5pbmR2IiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiKQoKIyBWaWV3KGFzLmRhdGEuZnJhbWUoUHJvcFN1Y2Nlc3NJbmQpKQoKYGBgCgoqKlBvc3NpYmxlIHBhcmFsb2dzIHBlciBpbmRpdmlkdWFsKioKCkluZGl2aWR1YWxzIHdpdGggaGlnaCBwcm9wb3J0aW9uIG9mIGxvY2kgZmxhZ2dlZCBhcyBwb3NzaWJsZSBwYXJhbG9ncyBzaG91bGQgYmUgZmxhZ2dlZCBhcyBwb3RlbnRpYWwgcHJvYmxlbSBpbmRpdmlkdWFscy4gCgpgYGB7ciBwb3NzIHBhcmFsb2dzIHBlciBpbmR2LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9pbmRfc3RhdHMsIGFlcyh4ID0gUG9zc19QYXJhbG9ncykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihQb3NzX1BhcmFsb2dzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX3N0YXRzKSowLjAxKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJubyBvZiBsb2NpIHBvdGVudGlhbCBwYXJhbG9ncyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDdXQtb2ZmIGZvciBpbmRpdmlkdWFscyB3aXRoIGxvY2kgZmxhZ2dlZCBwYXJhbG9ncyBpbiA+IDElIG9mIGxvY2kgaXMgYHIgbnJvdyhoYXBfc3RhdHMpKjAuMDFgLgoKYGBge3IgZmlsdGVyIHBhcmFsb2dzIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgUG9zc19QYXJhbG9ncyA+IDEwMCkKCiMgY3JlYXRlIHZlY3RvciBvZiBpbmR2IHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpClBvc3NfUGFyYWxvZ0luZCA8LSBmaWx0ZXIuaW5kLnBhcmFsb2dzKGhhcF9pbmRfc3RhdHMsIDEwMCkKCndyaXRlLnRhYmxlKFBvc3NfUGFyYWxvZ0luZCwgImRhdGEvUE9QR0VOL3Bvc3NQYXJhbC5pbmR2IiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiKQoKYGBgCgpUaGUgaGlnaGVzdCBudW1iZXIgb2YgZmxhZ2dlZCBsb2NpIGluIGFuIGluZGl2aWR1YWxzIGlzIGByIG1heChoYXBfaW5kX3N0YXRzJFBvc3NfUGFyYWxvZ3MsIG5hLnJtID0gVFJVRSlgLCB3aGljaCBpcyBlcXVpdmFsZW50IHRvIGByIHJvdW5kKG1heChoYXBfaW5kX3N0YXRzJFBvc3NfUGFyYWxvZ3MsIG5hLnJtID0gVFJVRSkvbnJvdyhoYXBfc3RhdHMpLCBkaWdpdHMgPSA0KSoxMDBgJSBvZiBsb2NpLgoKKipJbmRpdmlkdWFscyB3aXRoIGhpZ2ggcHJvcG9ydGlvbiBvZiBwb3RlbnRpYWwgYWxsZWxlIGRyb3BvdXQvZ2Vub3R5cGluZyBlcnJvcioqCgpgYGB7ciBnZW5vdHlwZyBlcnJvciBwZXIgaW5kdiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfaW5kX3N0YXRzLCBhZXMoeCA9IExvd19Db3ZlcmFnZS5FcnJvcnMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihMb3dfQ292ZXJhZ2UuRXJyb3JzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX3N0YXRzKSowLjAxKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGxvY2kgcG90ZW50aWFsIGdlbm90eXBpbmcgZXJyb3IiLCB5ID0gIiMgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpSZW1vdmUgaW5kaXZpZHVhbHMgd2l0aCBoaWdoIHByb3BvcnRpb24gb2YgbG9jaSB0aGF0IGhhdmUgYmVlbiBmbGFnZ2VkIGFzIHBvdGVudGlhbCBhbGxlbGUgZHJvcG91dHMvZ2Vub3R5cGluZyBlcnJvci4KCmBgYHtyIGZpbHRlciBnZW5vdHlwaW5nIGVycm9yIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgTG93X0NvdmVyYWdlLkVycm9ycyA+IDI4NSkKCiMgY3JlYXRlIHZlY3RvciBvZiBpbmR2IHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpCkdlbm9FcnJJbmR2IDwtIGZpbHRlci5pbmQuZ2Vub19lcnIoaGFwX2luZF9zdGF0cywgMjg1KQoKd3JpdGUudGFibGUoR2Vub0VyckluZHYsICJkYXRhL1BPUEdFTi9HZW5vRXJyLmluZHYiLCAKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UsIHNlcCA9ICJcdCIpCgojIFZpZXcoR2Vub0VyckluZHYpCgpgYGAKClRoZSBoaWdoZXN0IG51bWJlciBvZiBmbGFnZ2VkIGxvY2kgaW4gYW4gaW5kaXZpZHVhbHMgaXMgYHIgbWF4KGhhcF9pbmRfc3RhdHMkTG93X0NvdmVyYWdlLkVycm9ycywgbmEucm0gPSBUUlVFKWAsIHdoaWNoIGlzIGVxdWl2YWxlbnQgdG8gYHIgcm91bmQobWF4KGhhcF9pbmRfc3RhdHMkTG93X0NvdmVyYWdlLkVycm9ycywgbmEucm0gPSBUUlVFKS9ucm93KGhhcF9zdGF0cyksIGRpZ2l0cyA9IDQpKjEwMGAlIG9mIGxvY2kuCgojIyBGaWx0ZXIgZmxhZ2dlZCBsb2NpIGFuZCBpbmRpdmlkdWFscyBhcyBuZWNlc3NhcnkKCkxvYWQgZ2VuZXBvcCBmaWxlIHdpdGggaGFwbG90eXBlZCBsb2NpLgoKYGBge3IgbG9hZCBnZW5lcG9wLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBpbXBvcnQgZ2VuZXBvcCBmaWxlCmdlbiA8LSByZWFkLmdlbmVwb3AoZmlsZSA9ICJkYXRhL0hhcGxvdHlwaW5nL0JNQS5nZW4iLAogICAgICAgICAgICAgICAgICAgIG5jb2RlID0gM0wsIHF1aWV0ID0gRkFMU0UpCgpnZW4KCmBgYAoKUmVtb3ZlIGZsYWdnZWQgbG9jaSBhbmQgaW5kaXZpZHVhbHMuCgpgYGB7ciByZW1vdmUgbG9jaSBpbmRpdmlkdWFscywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gYyhQb3NzX1BhcmFsb2dzLCBOb1NOcHMsIE5vSGFwcywgR2Vub19FcnIsIFByb3BfSGFwbG90eXBlZCkKCmdlbiA8LSBnZW5pbmQucmVtLmxvY2koZ2VuLCByZW1vdmVsb2MpCgojIHJlbW92ZSBmbGFnZ2VkIGluZGl2aWR1YWxzCnJlbW92ZUluZCA8LSBjKFBvc3NfUGFyYWxvZ0luZCwgUHJvcFN1Y2Nlc3NJbmQsIEdlbm9FcnJJbmR2LAogICAgICAgICAgICAgICAiQk1BXzFBLUgwMl9NUzE4IiwgIkJNQV8xQi1DMDVfTVMtMjIiLCAiQk1BXzFCLUMwM19NUy0yMCIsICJCTUFfM0EtRDAxX0JNMDA2IikKZ2VuIDwtIGdlbi5pbmQucmVtLkluZChnZW4sIHJlbW92ZUluZCkKCmdlbgoKYGBgCgojIENvbXBhcmUgZHVwbGljYXRlIGluZGl2aWR1YWxzCgpgYGB7ciBjb21wIGR1bHBsaWNhdGUgaW5kdiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgZXh0cmFjdCBnZW5vdHlwZSBtYXRyaXgKZGYgPC0gZ2VuaW5kMmRmKGdlbiwKICAgICAgICAgICAgICAgIHVzZXBvcCA9IFRSVUUsCiAgICAgICAgICAgICAgICBzZXAgPSAiOiIsIG9uZUNvbFBlckFsbCA9IEZBTFNFKSAlPiUKICBzZWxlY3QoLXBvcCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCkKCiMgY3JlYXRlIGxpc3Qgb2YgZHVwbGljYXRlcwpwYWlycyA8LSBsaXN0KCkKCiMgaW5wdXQgZWFjaCBzZXQgb2YgZHVwbGljYXRlcyBhcyBhIHZlY3RvciBvZiBhIGxpc3QKcGFpcnNbWzFdXSA8LSBjKCJCTUFfM0ItRTEyX01TLTM3IiwgIkJNQV8yQS1DMDFfTVMtNTciKQpwYWlyc1tbMl1dIDwtIGMoIkJNQV8xQS1DMDFfQ0NHTi0wMDEiLCAiQk1BXzFBLUQwMl9DQ0dOMDEiKQpwYWlyc1tbM11dIDwtIGMoIkJNQV8xQS1IMDRfQ0MwMi0zNSIsCSJCTUFfMkItQjA5X0NDLTM1IikKcGFpcnNbWzRdXSA8LSBjKCJCTUFfM0ItSDAyX01TMjYiLCAiQk1BXzNCLUQwMV9NUzI2IikKcGFpcnNbWzVdXSA8LSBjKCJCTUFfMkItSDAyX01CMDYiLCAiQk1BXzFCLUUwNl9NQi0wNiIpCnBhaXJzW1s2XV0gPC0gYygiQk1BXzFCLUcxMV9DQy0wOCIsICJCTUFfMUEtSDAzX0NDMDItMDgiKQpwYWlyc1tbN11dIDwtIGMoIkJNQV8zQi1IMDNfQk0wMjciLCAiQk1BXzNCLUEwN19CTTAyNyIpCnBhaXJzW1s4XV0gPC0gYygiQk1BXzFCLUMwNF9NUy0yMSIsCSJCTUFfMkEtQzA1X01TLTYxIikKcGFpcnNbWzldXSA8LSBjKCJCTUFfMkItSDAxX0NTMyIsICJCTUFfMUEtQjAzX0NTLTAzIikKcGFpcnNbWzEwXV0gPC0gYygiQk1BXzNCLUUxMV9NUy0zNiIsICJCTUFfMUItQzEyX01TLTU2IikKcGFpcnNbWzExXV0gPC0gYygiQk1BXzJBLUMwN19NUy02MyIsICJCTUFfMUItQzA2X01TLTIzIikKcGFpcnNbWzEyXV0gPC0gYygiQk1BXzJCLUIwMV9DQy0xMiIsICJCTUFfM0EtQTAyX0NDLTEyIikKcGFpcnNbWzEzXV0gPC0gYygiQk1BXzJCLUcwNV9CTUFSLTAzIiwgIkJNQV8zQi1FMTJfQk1BUi0wMiIpCgoKIyBjcmVhdGUgZW1wdHkgbGlzdCBmb3IgZ2Vub3R5cGUgZXJyb3IgKGRpc2NvcmRhbnQgbG9jaSkKZ2Vub2Vycm9yIDwtIGxpc3QoKQoKIyBjcmVhdGUgZW1wdHkgdmVjdG9yIGZvciBkdXBsaWNhdGVzIChyZXRhaW5zIGZpcnN0IGluZHYgaW4gcGFpcikKZHVwIDwtIGNoYXJhY3RlcigpCgojIGlkZW50aWZ5IGRpc2NvcmRhbnQgZ2Vub3R5cGVzIGZvciBlYWNoIHNldCBvZiBkdXBsaWNhdGVzCmZvciAocCBpbiBwYWlycyl7CgojIHNlbGVjdCBkdXBsaWNhdGVzIGZyb20gZ2Vub3R5cGUgbWF0cml4Cmdlbm8gPC0gZGYgJT4lCiAgZmlsdGVyKHJvd25hbWUgJWluJSBwKSAlPiUKICBzZWxlY3QoLXJvd25hbWUpCgojIGNvbXBhcmUgZ2Vub3R5cGVzCmNvbXAgPC0gKHQoZ2VubykpCgpjb250aWdzIDwtIGFzLmRhdGEuZnJhbWUoY29tcCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJMT0NVUyIpICU+JQogIG11dGF0ZShWMSA9IGFzLmNoYXJhY3RlcihWMSksCiAgICAgICAgIFYyID0gYXMuY2hhcmFjdGVyKFYyKSkgJT4lCiAgZmlsdGVyKFYxICE9IFYyKQoKIyB3cml0ZSB2ZWN0b3Igd2l0aCBmaXJzdCBpbmRpdmlkdWFsIGluIHBhaXIKaW5kIDwtIHBbMV0KCmR1cCA8LSBjKGR1cCwgaW5kKQoKZ2Vub2Vycm9yW1tpbmRdXSA8LSBjb250aWdzCgp9CgojIGlmIGl0IHRocm93cyBlcnJvciBvYmplY3QgVjEgb3IgVjIgbm90IGZvdW5kIGl0IG1lYW5zIG9uZSBvciBtb3JlIG9mIHRoZSBzYW1wbGVzIG5hbWVzIGFyZSBub3QgY29ycmVjdCBvciBubyBsb25nZXIgaW4gZGF0YSBzZXQgYWZ0ZXIgZmlsdGVyaW5nCgojIGNvbWJpbmUgaW50byBvbmUgZGF0YWZyYW1lCmdlbm9lcnJvciA8LSBsZHBseShnZW5vZXJyb3IsIGRhdGEuZnJhbWUpICU+JQogIHJlbmFtZShEVVAxID0gYC5pZGAsCiAgICAgICAgIEdFTk9fSU5EVjEgPSBWMSwKICAgICAgICAgR0VOT19JTkRWMiA9IFYyKQoKd3JpdGVfZGVsaW0oZ2Vub2Vycm9yLCAicmVzdWx0cy9oYXBsb3R5cGVkLmdlbm9lcnJvciIsIGRlbGltID0gIlx0IikKCmBgYAoKQ29tcGFyZSBnZW5vdHlwZSBkZXB0aCBmb3IgZGlzY29yZGFudCBsb2NpOgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgaW1wb3J0IGdlbm90eXBlIGRlcHRoIGtlZXAgb25lIGRlcHRoIHBlciBjb250aWcKbiA8LSBucm93KGluZF9zdGF0c19GMTMpICsgMQoKZ2RlcHRoIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjEzLmdkZXB0aCIpICU+JQogIHNlbGVjdCgtUE9TKSAlPiUKICBkaXN0aW5jdChDSFJPTSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lCiAgZ2F0aGVyKGtleSA9IElORFYsIHZhbHVlID0gR0RFUFRILCAyOm4pICU+JQogIHJlbmFtZShMT0NVUyA9IENIUk9NKQoKIyBjcmVhdGUgZGF0YWZyYW1lIHdpdGggZHVwbGljYXRlcwpkdXBfaW5kdiA8LSBkYXRhLmZyYW1lKG1hdHJpeChuY29sID0gMiwgbnJvdyA9IDApKQpjb2xuYW1lcyhkdXBfaW5kdikgPC0gYygiRFVQMSIsICJEVVAyIikKCmZvciAocCBpbiBwYWlycyl7CgpwIDwtIGFzLmRhdGEuZnJhbWUodChwKSkKCmNvbG5hbWVzKHApIDwtICBjKCJEVVAxIiwgIkRVUDIiKQoKZHVwX2luZHYgPC0gYmluZF9yb3dzKGR1cF9pbmR2LCBwKQogICAKfQoKIyBhZGQgZHVwbGljYXRlIDIgdG8gZ2Vub2Vycm9yIGRhdGEgZnJhbWUKZ2Vub2Vycm9yIDwtIGxlZnRfam9pbihnZW5vZXJyb3IsIGR1cF9pbmR2KQoKIyBhZGQgZ2Vub3R5cGUgZGVwdGggaW5mb3JtYXRpb24gZm9yIGR1cGxpY2F0ZSAxCmdkZXB0aCA8LSBnZGVwdGggJT4lCiAgcmVuYW1lKERVUDEgPSBJTkRWKQoKZ2Vub2Vycm9yIDwtIGxlZnRfam9pbihnZW5vZXJyb3IsIGdkZXB0aCkgJT4lCiAgcmVuYW1lKEdERVBUSDEgPSBHREVQVEgpCgojIGFkZCBnZW5vdHlwZSBkZXB0aCBpbmZvcm1hdGlvbiBmb3IgZHVwbGljYXRlIDIKZ2RlcHRoIDwtIGdkZXB0aCAlPiUKICByZW5hbWUoRFVQMiA9IERVUDEpCgpnZW5vZXJyb3IgPC0gbGVmdF9qb2luKGdlbm9lcnJvciwgZ2RlcHRoKSAlPiUKICByZW5hbWUoR0RFUFRIMiA9IEdERVBUSCkKCiMgaWRlbnRpZnkgaG9tb3p5Z290ZSB2cyBoZXRlcm96eWdvdGUgZ2Vub3R5cGVzCmdlbm9lcnJvciA8LSBnZW5vZXJyb3IgJT4lCiAgc2VwYXJhdGUoY29sID0gR0VOT19JTkRWMSwgaW50byA9IGMoIkdFTk8xYSIsICJHRU5PMWIiKSwgc2VwID0gIjoiLCByZW1vdmUgPSBGQUxTRSkgJT4lCiAgc2VwYXJhdGUoY29sID0gR0VOT19JTkRWMiwgaW50byA9IGMoIkdFTk8yYSIsICJHRU5PMmIiKSwgc2VwID0gIjoiLCByZW1vdmUgPSBGQUxTRSkgJT4lCiAgbXV0YXRlKEdFTk9UWVBFMSA9IGlmZWxzZShHRU5PMWEgPT0gR0VOTzFiLCAiSE9NT1pZR09URSIsICJIRVRFUk9aWUdPVEUiKSwKICAgICAgICAgR0VOT1RZUEUyID0gaWZlbHNlKEdFTk8yYSA9PSBHRU5PMmIsICJIT01PWllHT1RFIiwgIkhFVEVST1pZR09URSIpKQoKYGBgCgpEZXRlcm1pbmUgbnVtYmVyIG9mIHRpbWVzIGRpc2NvcmRhbnQgZ2Vub3R5cGUgaXMgZHVlIHRvIGhldGVyb3p5Z290ZS9ob21venlnb3RlLgoKYGBge3J9Cgpjb3VudChnZW5vZXJyb3IsIEdFTk9UWVBFMSA9PSBHRU5PVFlQRTIpCgpgYGAKCkNvbXBhcmUgbnVtYmVyIG9mIGRpc2NvcmRhbnQgZ2Vub3R5cGUgY2FsbHMgcGVyIGR1cGxpY2F0ZSBzZXQuCgpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCnRvdGFsIDwtIGFzLm51bWVyaWMobGVuZ3RoKGxvY05hbWVzKGdlbikpKQoKIyBjb21wYXIgbnVtYmVyIG9mIGxvY2kgYnkgcGFpcgpwZXJfaW5kIDwtIGNvdW50KGdlbm9lcnJvciwgRFVQMSkgJT4lCiAgbXV0YXRlKGZyZXEgPSBuL3RvdGFsKjEwMCkKCmdncGxvdChwZXJfaW5kLCBhZXMoZnJlcSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMjUsIGZpbGwgPSAiZGFya29yYW5nZSIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDUpKSArCiAgbGFicyh4ID0gIiUgZ2Vub3R5cGluZyBlcnJvciBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpJZGVudGlmeSBsb2NpIGNvbnNpc3RlbnRseSBhZmZlY3RlZCBieSBnZW5vdHlwaW5nIGVycm9yCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKdG90YWwgPC0gYXMubnVtZXJpYyhsZW5ndGgocGFpcnMpKQoKIyBjb21wYXJlIGxvY2kgYWZmZWN0ZWQgYnkgZ2Vub3R5cGluZyBlcnJvcgpwZXJfbG9jIDwtIGNvdW50KGdlbm9lcnJvciwgTE9DVVMpICU+JQogIG11dGF0ZShmcmVxID0gbi90b3RhbCoxMDApICU+JQogIHJlbmFtZShMb2N1cyA9IExPQ1VTKQoKcGVyX2xvYyA8LSBsZWZ0X2pvaW4ocGVyX2xvYywgaGFwX3N0YXRzKQoKZ2dwbG90KHBlcl9sb2MsIGFlcyh4ID0gbikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiZGFya29yYW5nZSIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInNhbWUgbG9jdXMgYWZmZWN0ZWQgaW4gbiBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCmBgYHtyfQoKY291bnQocGVyX2xvYywgbiA+IDMpCgpgYGAKClJlbW92ZSBmbGFnZ2VkIGxvY2kgYW5kIG9uZSBpbmRpdmlkdWFsIHBlciBwYWlyLgoKYGBge3J9CgojIHdyaXRlIHZlY3RvciB3aXRoIHNlY29uZCBpbmRpdmlkdWFsIGluIHBhaXIgKGxvd2VyIHF1YWxpdHkpCnJtIDwtIGMoIkJNQV8yQS1DMDFfTVMtNTciLCAiQk1BXzFBLUQwMl9DQ0dOMDEiLCAiQk1BXzJCLUIwOV9DQy0zNSIsICJCTUFfM0ItRDAxX01TMjYiLCAiQk1BXzFCLUUwNl9NQi0wNiIsCiAgICAgICAgIkJNQV8xQS1IMDNfQ0MwMi0wOCIsICJCTUFfM0ItQTA3X0JNMDI3IiwgIkJNQV8yQS1DMDVfTVMtNjEiLCAiQk1BXzFBLUIwM19DUy0wMyIsICJCTUFfMUItQzEyX01TLTU2IiwKICAgICAgICAiQk1BXzFCLUMwNl9NUy0yMyIsICJCTUFfM0EtQTAyX0NDLTEyIiwgIkJNQV8zQi1FMTJfQk1BUi0wMiIpCgojIHJlbW92ZSBkdXBsaWNhdGVzCnJlbW92ZUluZCA8LSBybQoKZ2VuIDwtIGdlbi5pbmQucmVtLkluZChnZW4sIHJlbW92ZUluZCkKCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gZmlsdGVyKHBlcl9sb2MsIG4gPiAzKQpnZW4gPC0gZ2VuaW5kLnJlbS5sb2NpKGdlbiwgcmVtb3ZlbG9jKQoKZ2VuCgpgYGAKCmByIG5yb3codGVtcClgIGxvY2kgd2VyZSByZW1vdmVkIGFzIHBvdGVudGlhbGx5IGFmZmVjdGVkIGJ5IGdlbm90eXBpbmcgZXJyb3IuCgojIFJlbGF0ZWRuZXNzICYgSW5icmVlZGluZwoKQ3JlYXRlIGlucHV0IGZpbGUgZm9yZSBgcmVsYXRlZGAgcGFja2FnZS4KCmBgYHtyfQoKIyBuZWVkIHRvIGNoYW5nZSB0byBSIDMyCmxpYnJhcnkocmVsYXRlZCkKCiMgY3JlYXRlIGlucHV0IGZpbGUgLS0tLQpkZiA8LSBnZW5pbmQyZGYoZ2VuLCB1c2Vwb3AgPSBGQUxTRSwgb25lQ29sUGVyQWxsID0gVFJVRSkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJJTkRWIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlBPUCIsICJMSUIiLCAiSU5EViIpLCBzZXAgPSAiXyIsIGV4dHJhID0gIm1lcmdlIikgJT4lCiAgc2VsZWN0KC1QT1ApICU+JQogIHVuaXRlKElORCwgTElCLCBJTkRWLCBzZXAgPSAiXyIpCgojIG1pc3NpbmcgZGF0YSBtdXN0IGJlIDAKZGZbZGY9PSJOQSJdIDwtIDAKCndyaXRlLnRhYmxlKGRmLCAic2NyYXRjaC9yZWxhdGVkLmlucHV0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBzZXAgPSAiXHQiLCBxdW90ZSA9IEZBTFNFKQoKIyBpbXBvcnQgaW5wdXQgZmlsZSBhcyBsaXN0IChnZGF0YSwgbmxvY2ksIG5hbGxlbGVzLCBuaW5kcywgZnJlcXMpCmdlbm90eXBlZGF0YSA8LSByZWFkZ2Vub3R5cGVkYXRhKCJzY3JhdGNoL3JlbGF0ZWQuaW5wdXQiKQoKYGBgCgpDYWxjdWxhdGUgcGFpcndpc2UgcmVsYXRlZG5lc3MgYWNjb3JkaW5nIHRvIEx5bmNoICYgUml0bGFuZCAxOTk5OyB1c2VzIGluYnJlZWRpbmcgZXN0aW1hdGVzIGZvciBlYWNoIGluZGl2aWR1YWxzIHRvIGVzdGltYXRlIHJlbGF0ZWRuZXNzLgoKYGBge3IgbHluY2hyZCwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9N30KCiMgcGFpcndpc2UgcmVsYXRlZG5lc3MgKEx5bmNoICYgUml0bGFuZCAxOTk5KQpyZWxhdGVkbmVzc19seW5jaHJkIDwtIGNvYW5jZXN0cnkoZ2Vub3R5cGVkYXRhJGdkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHluY2hyZCA9IDEpCgpyZWxhdGVkbiA8LSByZWxhdGVkbmVzc19seW5jaHJkJHJlbGF0ZWRuZXNzICU+JQogIHNlbGVjdChwYWlyLm5vLCBpbmQxLmlkLCBpbmQyLmlkLCBseW5jaHJkKQoKd3JpdGVfZGVsaW0ocmVsYXRlZG4sICJyZXN1bHRzL3BhaXJ3aXNlX3JlbGF0ZWRuZXNzIikKCmluYnJlZWQgPC0gcmVsYXRlZG5lc3NfbHluY2hyZCRpbmJyZWVkaW5nICU+JQogIHNlbGVjdChpbmQuaWQsIEwzLCBMSCkgJT4lCiAgcmVuYW1lKElORFYgPSBpbmQuaWQpCgp3cml0ZV9kZWxpbShpbmJyZWVkLCAicmVzdWx0cy9pbmJyZWVkaW5nIikKCmBgYAoKRGlzdHJpYnV0aW9uIG9mIGxldmVscyBvZiBwYWlyd2lzZSByZWxhdGVkbmVzczoKCmBgYHtyIGx5bmNocmQgZGlzdHJpYiByZWxhdGVkbiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OH0KCmdncGxvdChyZWxhdGVkbiwgYWVzKHggPSBseW5jaHJkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMDI1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihseW5jaHJkLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUobHluY2hyZCwgMC45NSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfeV9zcXJ0KCkgKwogIGxhYnMoeCA9ICJyZWxhdGVkbmVzcyIsIHkgPSAibnVtYmVyIG9mIHBhaXJzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBsZXZlbHMgb2YgaG9tb3p5Z29zaXR5OgoKYGBge3IgbHluY2hyZCBpbmJyZWVkaW5nLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00fQoKZ2dwbG90KGluYnJlZWQsIGFlcyh4ID0gTDMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTEgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBxdWFudGlsZShMSCwgMC45NSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gImluYnJlZWRpbmcgY29lZmZpY2llbnQiLCB5ID0gImluZGl2aWR1YWxzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCiMgSGV0ZXJvenlnb3NpdHkgYW5kIEhXRQoKR2VuZXJhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KClNhbXBsZUluZm8gPC0gcmVhZF9kZWxpbSgiZGF0YS9QT1BHRU4vU2FtcGxlSW5mby50eHQiLCBkZWxpbSA9ICJcdCIpICU+JQogIGRpc3RpbmN0KFNBTVBMRV9JRCwgLmtlZXBfYWxsID0gVFJVRSkKCkluZHMgPC0gYXMuZGF0YS5mcmFtZShpbmROYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTElCX0lEID0gYGluZE5hbWVzKGdlbilgKSAlPiUKICBzZXBhcmF0ZShMSUJfSUQsIGludG8gPSBjKCJTUCIsICJXRUxMIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIGV4dHJhID0gIm1lcmdlIiwgcmVtb3ZlID0gRkFMU0UpCgpzdHJhdGEgPC0gbGVmdF9qb2luKEluZHMsIFNhbXBsZUluZm8pICU+JQogIGRpc3RpbmN0KCkgJT4lCiAgbXV0YXRlKFBPUCA9IG9yZGVyZWQoUE9QLCBsZXZlbHMgPSBwb3BzKSkgJT4lCiAgbXV0YXRlKFJFR0lPTiA9IGNhc2Vfd2hlbihQT1AgJWluJSBjKCJGTEEiKSB+ICJTV0FUTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT1AgJWluJSBjKCJDQU1QIikgfiAiU0dVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiRkxHUyIsICJGTEdOIikgfiAiRUdVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIpIH4gIkNHVUxGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBPUCAlaW4lIGMoIkNDIikgfiAiV0dVTEYiLCksCiAgICAgICAgIE9DRUFOID0gaWZlbHNlKFBPUCA9PSAiRkxBIiwgIkFUTCIsICJHVUxGIikpCgpzdHJhdGEoZ2VuKSA8LSBzdHJhdGEKCiMgZGVmaW5lIGdyb3VwcyB1c2luZyBzdHJhdGEgaW5mb3JtYXRpb24gLSBuZWVkIHRvIGFkZCBQT1AgZm9yIG1pc3Npbmcgb25lcwpzZXRQb3AoZ2VuKSA8LSB+UE9QCgojIGdlbmVyYXRlIGdlbmV0aWMgZGl2ZXJzaXR5IHN0YXRzCkdlbkRpdiA8LSBhZGVnZW5ldDo6c3VtbWFyeShnZW4pCgpkYXQgPC0gaGllcmZzdGF0Ojo6LmdlbmluZDJoaWVyZnN0YXQoZ2VuKQpHZW5EaXYyIDwtIGJhc2ljLnN0YXRzKGRhdCkKCmBgYAoKQ29tcGFyZSBvYnNlcnZlZCAoSG8pIGFuZCBleHBlY3RlZCAoSGUpIGhldGVyb3p5Z29zaXR5IGZvciBhbGwgaW5kaXZpZHVhbHMgYWNyb3NzIGFsbCBwb3B1bGF0aW9ucy4KCmBgYHtyfQoKIyBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBwZXIgbG9jdXMKSG8gPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYkSG9icykgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiTE9DVVMiKSAlPiUKICByZW5hbWUoSG8gPSBgR2VuRGl2JEhvYnNgKQoKIyBleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBwZXIgbG9jdXMKSHMgPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYkSGV4cCkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiTE9DVVMiKSAlPiUKICByZW5hbWUoSGV4cCA9IGBHZW5EaXYkSGV4cGApCgojIGV4cGVjdGVkIGFuZCBvYnNlcnZlZCBoZXRlcm96eXNpdHkgcGVyIGxvY3VzCkhldCA8LSBsZWZ0X2pvaW4oSG8sIEhzLCBieSA9ICJMT0NVUyIpCgpgYGAKCklkZW50aWZ5IGxvY2kgdGhhdCBhcmUgbm93IG1vbm9tb3JwaGljIGFuZCByZW1vdmUgZnJvbSBkYXRhIHNldDoKCmBgYHtyfQoKbW9ub21vcnBoaWMgPC0gZmlsdGVyKEhvLCBIbyA9PSAwKQoKbW9ub21vcnBoaWMgPC0gbW9ub21vcnBoaWMkTE9DVVMKCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gYyhtb25vbW9ycGhpYykKZ2VuIDwtIGdlbmluZC5yZW0ubG9jaShnZW4sIHJlbW92ZWxvYykKCmdlbgoKYGBgCgpFeHBlY3RlZCB2cyBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBhY3Jvc3MgYWxsIHBvcHVsYXRpb25zLgoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NH0KCnRlbXAgPC0gSGV0ICU+JQogIGZpbHRlcihIbyAhPSAwKQoKIyBwbG90IEhvIHZzIEhzIGFjcm9zcyBhbGwgaW5kaXZpZHVhbHMKZ2dwbG90KHRlbXAsIGFlcyh4ID0gSG8sIHkgPSBIZXhwKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHhsaW0oMCwgMSkgKwogIHlsaW0oMCwgMSkgKwogIGxhYnMoeCA9ICJvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBIbyIsIHkgPSAid2l0aGluIGNsdXN0ZXIgZGl2ZXJzaXR5IEhzIChIZXhwKSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSAoSG8pIGluIGVhY2ggcHV0YXRpdmUgcG9wdWxhdGlvbjoKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTR9CgpIb19wZXIgPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYyJEhvKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oIkxPQ1VTIikgJT4lCiAgcmVuYW1lKENBTVAgPSBgMWAsIEZMR1MgPSBgMmAsIEZMR04gPSBgM2AsIEZMQSA9IGA0YCwgQ1MgPSBgNWAsIAogICAgICAgICBDQyA9IGA2YCwgTUlTUyA9IGA3YCwgTEEgPSBgOGAsIE1CID0gYDlgKSAlPiUKICBzZWxlY3QoTE9DVVMsIENBTVAsIEZMR1MsIEZMR04sIEZMQSwgQ1MsIENDLCBNSVNTLCBMQSwgTUIpICU+JQogIGdhdGhlcihHcm91cCwgSG8sIDI6MTApICU+JQogIG11dGF0ZShQT1AgPSBvcmRlcmVkKEdyb3VwLCBsZXZlbHMgPSBwb3BzKSkgJT4lCiAgbXV0YXRlKFJFR0lPTiA9IGNhc2Vfd2hlbihQT1AgJWluJSBjKCJGTEEiKSB+ICJTV0FUTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT1AgJWluJSBjKCJDQU1QIikgfiAiU0dVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiRkxHUyIsICJGTEdOIikgfiAiRUdVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIpIH4gIkNHVUxGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBPUCAlaW4lIGMoIkNDIikgfiAiV0dVTEYiLCksCiAgICAgICAgIE9DRUFOID0gaWZlbHNlKFBPUCA9PSAiRkxBIiwgIkFUTCIsICJHVUxGIikpCgojIGNvbXBhcmUgb2JzZXJ2ZWQgaGV0ZXJvenlnb3NpdHkgcGVyIGxvY3VzIGFuZCBjbHVzdGVyCmdncGxvdChIb19wZXIsIGFlcyh4ID0gR3JvdXAsIHkgPSBIbywgZmlsbCA9IFJFR0lPTikpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh4ID0gIkdyb3VwIiwgeSA9ICJIbyIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xfcmVncykgKwogIHRoZW1lX3N0YW5kYXJkICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBIZSwgKHdpdGhpbiBjbHVzdGVyIGRpdmVyc2l0eSkgaW4gZWFjaCBwdXRhdGl2ZSBwb3B1bGF0aW9uOgoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NX0KCiMgd2l0aGluIGNsdXN0ZXIgZGl2ZXJzaXR5L2V4cCBkaXZlcnNpdHkgcGVyIGxvY3VzIChyb3dzKSBhbmQgY2x1c3RlciAoY29sdW1ucykKSHNfcGVyIDwtIGFzLmRhdGEuZnJhbWUoR2VuRGl2MiRIcykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJMT0NVUyIpICU+JQogIHJlbmFtZShDQU1QID0gYDFgLCBGTEdTID0gYDJgLCBGTEdOID0gYDNgLCBGTEEgPSBgNGAsIENTID0gYDVgLCAKICAgICAgICAgQ0MgPSBgNmAsIE1JU1MgPSBgN2AsIExBID0gYDhgLCBNQiA9IGA5YCkgJT4lCiAgc2VsZWN0KExPQ1VTLCBDQU1QLCBGTEdTLCBGTEdOLCBGTEEsIENTLCBDQywgTUlTUywgTEEsIE1CKSAlPiUKICBnYXRoZXIoR3JvdXAsIEhzLCAyOjkpCgojIGNvbXBhcmUgZXhwZWN0ZWQgaGV0ZXJvenlnb3NpdHkgcGVyIGxvY3VzIGFuZCBjbHVzdGVyCmdncGxvdChIc19wZXIsIGFlcyh4ID0gR3JvdXAsIHkgPSBIcykpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh4ID0gIkdyb3VwIiwgeSA9ICJleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBIbyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDb21wYXJpc29uIG9mIG9iZXJ2ZWQgdnMuIGhldGVyb3p5Z29zaXR5IHdpdGhpbiBlYWNoIHBvcHVsYXRpb246CgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGpvaW4gZGF0YSBmcmFtZXMKSGV0X3BlciA8LSBsZWZ0X2pvaW4oSHNfcGVyLCBIb19wZXIpCgojIHBsb3QgcGVyIGNsdXN0ZXIKZ2dwbG90KEhldF9wZXIsIGFlcyh4ID0gSG8sIHkgPSBIcykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMTksIHNpemUgPSAxKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHhsaW0oMCwgMSkgKwogIHlsaW0oMCwgMSkgKwogIGZhY2V0X2dyaWQoLiB+IEdyb3VwKSArCiAgbGFicyh4ID0gIm9ic2VydmVkIGhldGVyb3p5Z29zaXR5IEhvIiwgeSA9ICJ3aXRoaW4gY2x1c3RlciBkaXZlcnNpdHkgSHMgKEhleHApIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKClRlc3QgZm9yIGRldmlhdGlvbnMgZnJvbSBIYXJkeS1XZWluYmVyZyBlcXVpbGlicml1bSB3aXRoaW4gZWFjaCBncm91cCAoUE9QIGxldmVsKToKCmBgYHtyfQoKc2V0UG9wKGdlbikgPC0gflBPUAoKcG9wTmFtZXMoZ2VuKQoKIyBzaG91bGQgYmUgYWJsZSB0byB1c2UgbGFwcGx5CkhXRSA8LSBzZXBwb3AoZ2VuKSAlPiUKICAgbGFwcGx5KGh3LnRlc3QsIEI9MTAwMCkKCkhXRVtbIkFMTCJdXSA8LSBody50ZXN0KGdlbiwgQiA9IDEwMDApCgojIGNvbnZlcnQgdG8gZGF0YS5mcmFtZXMKaHdlIDwtIGxpc3QoKQoKZm9yIChtIGluIG5hbWVzKEhXRSkpIHsKICAgaHdlW1ttXV0gPC0gYXMuZGF0YS5mcmFtZShIV0VbW21dXSkgJT4lCiAgIHJlbmFtZShwdmFsID0gUHIuZXhhY3QpICU+JQogICByb3duYW1lc190b19jb2x1bW4oIkxPQ1VTIikgJT4lCiAgIHNlbGVjdChMT0NVUywgcHZhbCkKfQoKaHdlIDwtIGxkcGx5KGh3ZSwgZGF0YS5mcmFtZSkgJT4lCiAgIHJlbmFtZShQT1AgPSBgLmlkYCkgJT4lCiAgIG11dGF0ZShIV0UgPSBpZmVsc2UocHZhbCA8PSAwLjA1LCAiT1VUIiwgIklOIikpCgp3cml0ZV9kZWxpbShod2UsICJyZXN1bHRzL0hXRWJ5cG9wIiwgZGVsaW0gPSAiXHQiKQoKaHdlIDwtIHJlYWRfZGVsaW0oInJlc3VsdHMvSFdFYnlwb3AiLCBkZWxpbSA9ICJcdCIpCgpod2VfcGVycG9wIDwtIGh3ZSAlPiUKICBncm91cF9ieShQT1ApICU+JQogIGNvdW50KEhXRSkKCmh3ZV9wZXJsb2MgPC0gaHdlICU+JQogIGZpbHRlcihQT1AgIT0gIkFMTCIpICU+JQogIGdyb3VwX2J5KExPQ1VTKSAlPiUKICBjb3VudChIV0UpICU+JQogIGZpbHRlcihIV0UgPT0gIk9VVCIpCgpgYGAKCkZvcm1hdCBvdXRwdXQgYW5kIHZpZXcgcmVzdWx0czoKCmBgYHtyIEhXRSByZXN1bHRzLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcGxvdCBkYXRhCmdncGxvdChod2VfcGVycG9wLCBhZXMoeCA9IEhXRSwgeSA9IG4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGxhYnMoeCA9ICJzaWduaWZpY2FudCBkZXZpYXRpb24gZnJvbSBIV0UgKHAgPiAwLjA1KSIsIHkgPSAibnVtYmVyIG9mIGxvY2kiKSArCiAgZmFjZXRfZ3JpZCggfiBQT1ApICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpEaXN0cmlidXRpb24gb2YgbnVtYmVyIG9mIHRpbWVzIGxvY2kgYXJlIG91dCBvZiBIV0UKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTR9CgpnZ3Bsb3QoaHdlX3BlcmxvYywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgbGFicyh4ID0gIm5vIHBvcHVsYXRpb25zIG91dCBvZiBIV0UiLCB5ID0gIm5vLiBsb2NpIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKClJlbW92ZSBsb2NpIG91dCBvZiBIV0UgaW4gNSBvciBtb3JlIHBvcHVsYXRpb25zOgoKYGBge3J9CgojIHJlbW92ZSBmbGFnZ2VkIGxvY2kKcmVtb3ZlbG9jIDwtIGh3ZV9wZXJsb2MgJT4lCiAgZmlsdGVyKG4gPj0gNSkKCmdlbiA8LSBnZW5pbmQucmVtLmxvY2koZ2VuLCByZW1vdmVsb2MkTE9DVVMpCgpnZW4KCmBgYAoKIyBGaW5hbCBkYXRhIHNldAoKV3JpdGUgZmlsZXMgd2l0aCBmaWx0ZXJlZCBkYXRhIHNldDoKCmBgYHtyIHdyaXRlIGZpbHRlcmVkIGRhdGEgc2V0fQoKbGlicmFyeShyYWRpYXRvcikKCnNldFBvcChnZW4pIDwtIH5QT1AKCiMgY29udmVydCB0byB0aWR5IGRhdGEgc2V0CnRpZHkgPC0gdGlkeV9nZW5vbWljX2RhdGEoZGF0YSA9IGdlbiwgZmlsZW5hbWUgPSBOVUxMKSAlPiUKICBkcGx5cjo6c2VsZWN0KDE6NikKCiMgd3JpdGUgdGlkeSBkYXRhIHNldCB0byBmaWxlCndyaXRlX2RlbGltKHRpZHksICJkYXRhL1BPUEdFTi9CTUEudGlkeS5nZW5vdHlweWVzIiwgZGVsaW0gPSAiXHQiKQoKIyB3cml0ZSBnZW5lcG9wIGZpbGUKd3JpdGVfZ2VuZXBvcChkYXRhID0gdGlkeSwKICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJkYXRhL1BPUEdFTi9CTUFfYnlfcG9wIiwKICAgICAgICAgICAgICBnZW5lcG9wLmhlYWRlciA9ICJnYWZmdG9wIHNhaWwgY2F0ZmlzaCBncm91cGVkIGJ5IHBvcHVsYXRpb24iKQoKYGBgCgpXcml0ZSBmaWxlcyB3aXRoIGluZGl2aWR1YWxzIGFuZCBDb250aWdzIHN0aWxsIGNvbnRhaW5lZCBpbiBkYXRhIHNldCBhbmQgdXNlIHRvIGZpbHRlciB2Y2YgZmlsZS4KCmBgYHtyfQoKa2VlcGxvY2kgPC0gYXMuZGF0YS5mcmFtZShsb2NOYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTE9DVVMgPSBgbG9jTmFtZXMoZ2VuKWApCgprZWVwbG9jaSA8LSBmaWx0ZXIobG9jX3N0YXRzX0YxMywgQ0hSICVpbiUga2VlcGxvY2kkTE9DVVMpICU+JQogIHNlbGVjdChDSFIsIFBPUykKCndyaXRlLnRhYmxlKGtlZXBsb2NpLCAiZGF0YS9WQ0YvZmlsdGVyZWQubG9jaSIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmtlZXBpbmQgPC0gYXMuZGF0YS5mcmFtZShpbmROYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTElCX0lEID0gYGluZE5hbWVzKGdlbilgKSAKCmtlZXBpbmQgPC1maWx0ZXIoaW5kX3N0YXRzX0YxMywgSU5EViAlaW4lIGtlZXBpbmQkTElCX0lEKSAlPiUKICBzZWxlY3QoSU5EVikKCndyaXRlLnRhYmxlKGtlZXBpbmQsICJkYXRhL1ZDRi9maWx0ZXJlZC5pbmQiLAogICAgICAgICAgICBjb2wubmFtZXMgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKCldyaXRlIHZjZiBmaWxlIGFuZCAwMTIgZm9ybWF0OgoKYGBge2Jhc2h9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQSAtLXBvc2l0aW9ucyBkYXRhL1ZDRi9maWx0ZXJlZC5sb2NpIC0ta2VlcCBkYXRhL1ZDRi9maWx0ZXJlZC5pbmQgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9QT1BHRU4vQk1BIC0tMDEyCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1zaXRlLW1lYW4tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLmZpbCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1oZXQKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0taGFyZHkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLmZpbCAtLWdlbm8tZGVwdGgKCmBgYAoKQ29tcGFyZSBzdGF0cyBmb3IgZmluYWwgZmlsdGVyZWQgZGF0YSBzZXQ6CiAgICAKYGBge3Igc3RhdHMgZmluYWwsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19maWwgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5maWwiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX2ZpbCA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5maWwiKQoKVmlldyhpbmRfc3RhdHNfZmlsKQpWaWV3KGhhcF9pbmRfc3RhdHMpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHBlciBpbmR2IC0tLS0KcDIgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gRmlzX0JNQS5maWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMyA8LSBnZ3Bsb3QoaW5kX3N0YXRzX2ZpbCwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5maWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIHJlYWQgZGVwdGggcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkZXB0aCB2cyBtaXNzaW5nIC0tLS0KcDQgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuZmlsLCB5ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBpbmR2IiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IEZpcyB2cyBtaXNzaW5nIGRhdGEgcGVyIGluZHYgLS0tLQpwNSA8LSBnZ3Bsb3QoaW5kX3N0YXRzX2ZpbCwgYWVzKHggPSBGaXNfQk1BLmZpbCwgeSA9IE1JU1NfQk1BLmZpbCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgdnMgbWVhbiBkZXB0aCBwZXIgaW5kdiAtLS0tCnA2IDwtIGdncGxvdChpbmRfc3RhdHNfZmlsLCBhZXMoeCA9IEZpc19CTUEuZmlsLCB5ID0gTUVBTl9ERVBUSF9CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIsIHkgPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRpc3RyaWJ1dGlvbiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIC0tLS0KcDcgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiJSBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1lYW4gcmVhZCBkZXB0aCAtLS0tCnA4IDwtIGdncGxvdChsb2Nfc3RhdHNfZmlsLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLmZpbCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19maWwsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuZmlsLCB5ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEwIDwtIGxvY19zdGF0c19maWwgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnRlbXAgPC0gbG9jX3N0YXRzX2ZpbCAlPiUKICBjb3VudChDSFIpCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnAxMSA8LSBsZWZ0X2pvaW4odGVtcCwgbG9jX3N0YXRzX2ZpbCkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBuLCB5ID0gTUVBTl9ERVBUSF9CTUEuZmlsKSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgY29udGlnIiwgeSA9ICJtZWFuIGRlcHRoIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgU05QIHF1YWxpdHkgLS0tLQpzaXRlX3F1YWwgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLmZpbC5scXVhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIG11dGF0ZShQUk9CID0gMTBeKC1RVUFMLzEwKSkKCnRlbXAgPC0gZGF0YS5mcmFtZShsb2Nfc3RhdHNfZmlsJE1FQU5fREVQVEhfQk1BLmZpbCwgc2l0ZV9xdWFsJFFVQUwpICU+JQogIHJlbmFtZShkZXB0aCA9IGxvY19zdGF0c19maWwuTUVBTl9ERVBUSF9CTUEuZmlsLCBxdWFsID0gc2l0ZV9xdWFsLlFVQUwpCgpwMTIgPC0gZ2dwbG90KHRlbXAsIGFlcyh4ID0gZGVwdGgsIHkgPSBxdWFsKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihkZXB0aCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihxdWFsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAiU05QIHF1YWxpdHkiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm1maWwgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIGNvbHM9MikKCmBgYAo=